From 6431cad59bda3da4bafb58fdf91f6a946e42af43 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Sun, 20 Sep 2026 17:44:02 +0000 Subject: Surface a dead OAuth grant instead of reporting it as connected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B --- migrations/035_oauth_token_errors.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 migrations/035_oauth_token_errors.sql (limited to 'migrations/035_oauth_token_errors.sql') diff --git a/migrations/035_oauth_token_errors.sql b/migrations/035_oauth_token_errors.sql new file mode 100644 index 0000000..c0100c0 --- /dev/null +++ b/migrations/035_oauth_token_errors.sql @@ -0,0 +1,14 @@ +-- Record why an OAuth token stopped working. +-- +-- A stored token row was treated as "connected", full stop. When the refresh +-- token itself goes bad — Google answers invalid_grant, which happens when it +-- is revoked, superseded, or (for an OAuth client still in Testing publishing +-- status) simply older than seven days — settings still showed Google Tasks as +-- connected while every fetch failed in the background. +-- +-- Persisting the failure lets settings say "reconnect" instead of "connected", +-- which is the difference between a five-second fix and not knowing anything +-- is wrong. Cleared on the next successful refresh. + +ALTER TABLE oauth_tokens ADD COLUMN last_error TEXT; +ALTER TABLE oauth_tokens ADD COLUMN last_error_at DATETIME; -- cgit v1.2.3