Skip to content

fix: gmail pageToken reuse + slack bot token unhandled rejection#54

Merged
meidad merged 1 commit into
mainfrom
fix/gmail-cursor-and-slack-bot-token
May 27, 2026
Merged

fix: gmail pageToken reuse + slack bot token unhandled rejection#54
meidad merged 1 commit into
mainfrom
fix/gmail-cursor-and-slack-bot-token

Conversation

@meidad
Copy link
Copy Markdown
Collaborator

@meidad meidad commented May 27, 2026

Summary

Two daemon-startup regressions that surfaced after #53 merged:

Gmail Invalid pageToken on every delta run

The pipeline stores lastMessage.id as the cursor and passes it back to the source on the next run; the Gmail source was treating that as Gmail's pageToken. They're different beasts — message IDs are short hex strings, pageTokens are opaque intra-run pagination handles. Cross-run reuse always 400s with Invalid pageToken.

Fix: stop using the inherited cursor as pageToken in src/ingest/sources/gmail.ts. Re-running the same q: is safe because the pipeline's per-message dedup step rejects already-stored messages, so a fresh full scan is idempotent (verified: 4 messages skipped via dedup on a re-run). Delta semantics come from options.since (computed by the ingest scheduler from the last successful job), which still works.

Slack User adapter account_inactive unhandled rejection

When the workspace's bot token was deactivated, the bot client's own auth.test() was wrapped in try/catch, but the Bolt App was being constructed with the bad bot token before validation. Bolt's internal auth.test fired an uncaught promise.

Fix: validate the bot token via botClient.auth.test() before handing it to Bolt in src/daemon/channels/slack-user.ts. On failure, drop the bot client and fall back to the user token for Bolt's Socket Mode connection. Same user-facing behavior (agent posts as user), just no more stack trace at startup.

Test plan

  • Run `pnpm dev ingest gmail --since 2026-05-25 --run-type delta` against an install with a stored `last_cursor`; verify no `Invalid pageToken` and messages either ingest or are skipped by dedup.
  • Run `pnpm dev ingest gmail --since 2026-05-25` from scratch; verify clean ingest end-to-end.
  • Restart the daemon with a workspace whose bot token has been deactivated (or invalidate it intentionally); verify the log shows `Bot token auth failed -- agent will post as user` instead of an unhandled rejection stack trace, and that the user-mode adapter still starts cleanly.

🤖 Generated with Claude Code

Two daemon-startup regressions surfaced after multi-account rolled out:

1. Gmail delta ingest hit `Invalid pageToken` on every run. The
   pipeline stores `lastMessage.id` as the cursor and passes it back
   to the source on the next run; the source was treating that as
   Gmail's `pageToken`. They're different beasts — message IDs are
   short hex strings, pageTokens are opaque intra-run pagination
   handles. Cross-run reuse always 400s.

   Fix: stop using the inherited cursor as pageToken. Re-running the
   same `q:` is safe because the pipeline's per-message dedup step
   rejects already-stored messages, so a fresh full scan is
   idempotent (verified: 4 messages skipped via dedup on a re-run).
   Delta semantics come from `options.since` (computed by the ingest
   scheduler from the last successful job), which still works.

2. Slack User adapter logged an unhandled `account_inactive`
   rejection when the workspace's bot token was deactivated. The
   bot client's own auth.test was wrapped in try/catch, but the Bolt
   App was being constructed with the bad bot token before
   validation, and its internal auth.test fired an uncaught promise.

   Fix: validate the bot token via `botClient.auth.test()` BEFORE
   handing it to Bolt. On failure, drop the bot client and fall back
   to the user token for Bolt's Socket Mode connection. Same user-
   facing behavior (agent posts as user), just no more stack trace
   at startup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@meidad meidad merged commit a9a4901 into main May 27, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant