<feed xmlns='http://www.w3.org/2005/Atom'>
<title>doot.git/migrations/035_oauth_token_errors.sql, branch master</title>
<subtitle>doot — personal productivity web app
</subtitle>
<id>https://git.terst.org/doot.git/atom?h=master</id>
<link rel='self' href='https://git.terst.org/doot.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.terst.org/doot.git/'/>
<updated>2026-09-20T17:44:02+00:00</updated>
<entry>
<title>Surface a dead OAuth grant instead of reporting it as connected</title>
<updated>2026-09-20T17:44:02+00:00</updated>
<author>
<name>Peter Stone</name>
<email>thepeterstone@gmail.com</email>
</author>
<published>2026-09-20T17:44:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.terst.org/doot.git/commit/?id=6431cad59bda3da4bafb58fdf91f6a946e42af43'/>
<id>urn:sha1:6431cad59bda3da4bafb58fdf91f6a946e42af43</id>
<content type='text'>
With the cancelled-context bug fixed, the refresh actually reaches Google and
the real state of the Google Tasks grant becomes visible: it answers
invalid_grant. The stored refresh token has been dead since roughly 2026-08-16.
The earlier bug had been masking this — the refresh never got far enough to be
rejected.

Settings treated the presence of a token row as "Connected", so it reported
Google Tasks as connected for a month while every fetch failed. A refresh
failure is now persisted (migration 035 adds last_error/last_error_at to
oauth_tokens) and cleared on the next success, and settings reports "connected"
only when there is no recorded failure.

invalid_grant is classified specially, because it is the one failure retrying
cannot fix: the message tells the user to reconnect, and notes that a weekly
recurrence means the OAuth client is still in Testing publishing status, where
Google expires refresh tokens after seven days. Other errors — a network blip,
a 5xx — are left as transient rather than pushing the user through consent
needlessly.

Reconnecting at /settings is still a manual step; nothing here can perform
consent on the user's behalf.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
</content>
</entry>
</feed>
