Skip to content

fix: stop task polling once the session is rejected - #297

Open
andyhsu6 wants to merge 1 commit into
mainfrom
fix/task-polling-401-loop
Open

andyhsu6 wants to merge 1 commit into
mainfrom
fix/task-polling-401-loop

Conversation

@andyhsu6

Copy link
Copy Markdown
Owner

Why

A user reported "one chapter ran for an hour and nothing came out". The backend had actually written four chapters in that window (18:36–19:18, all status=completed, last one 3,488 chars). The UI never showed them.

Root cause, from the backend access log:

4555  GET  /api/tasks?project_id=...        -> 401 Unauthorized
   2  POST /api/chapters/batch-generate/<id>/cancel -> 401 Unauthorized

backgroundTaskService talks to the API with raw fetch, so the axios response interceptor in services/api.ts — the only place that redirects 401 to /login — never applied to it. FloatingTaskPanel.loadTasks caught the failure and only called console.error, while its setInterval kept polling every 15s. Net effect: the task panel stays on stale state forever, and cancelling a batch silently fails.

What

  • backgroundTaskService: TaskRequestError now carries status and code; new isTaskAuthError() reuses errorMapper.isUnauthenticatedError.
  • FloatingTaskPanel: on an auth failure, set a ref that short-circuits further loads, warn once, and route to /login (same guard as the axios interceptor: skipped when already there).

No new user-facing strings, so no locale changes.

Test plan

  • npx tsc -b → exit 0
  • npm test (node:test + vitest) → 28 files / 233 tests passed
  • New case in error-contract.test.ts: 401 is reported as an auth error, 500 is not, while the existing "action prefix + mapped envelope" message contract is unchanged.
  • npm run build → built successfully.
  • Not covered: reproducing a real expired session end-to-end in the browser. The 401 branch is asserted at unit level only; the normal path is unchanged.

This is independent of the generation-latency work in #296.

The background task panel uses raw fetch, so the axios interceptor that
redirects 401 responses to /login never applied to it, and loadTasks only
logged the error while setInterval kept firing.

One local session recorded 4,555 unauthorized task-list polls and two
failed batch cancels. The panel stayed on stale state, so a batch that
actually wrote its chapters looked like "nothing happened".

Attach status/code to the request error, expose isTaskAuthError, and stop
polling + route to /login when the session is rejected.
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