Skip to content

fix: bound provider requests with a 60s timeout (scans can no longer hang)#20

Merged
New1Direction merged 1 commit into
mainfrom
fix/scan-timeout
Jun 15, 2026
Merged

fix: bound provider requests with a 60s timeout (scans can no longer hang)#20
New1Direction merged 1 commit into
mainfrom
fix/scan-timeout

Conversation

@New1Direction

Copy link
Copy Markdown
Owner

The bug

A scan was hanging until the output tab gave up with Analysis timed out — please try again. (output-tab.js:127, the 90s waitForData deadline). Root cause: every provider fetch() in the AI path had no AbortController/timeout, so a stalled connection froze the serialized scan queue indefinitely — the tab's generic 90s timeout was the only escape, and it surfaced no actionable next step.

The fix

  • fetchWithTimeout() wraps all 8 provider fetch sites (callOpenAICompatible, openaiChat, callAnthropicCompatible, callAnthropic, callGemini, callNous, callOpenRouter, callXAI) with a 60s AbortController timeout — generous for slow models, well under the 90s tab deadline.
  • New non-retryable timeout error kind (errors.js): a stall falls straight to the next provider in the attempt plan instead of withRetry re-hammering the stuck one (which would've made it worse), and surfaces "{provider} took too long — Retry, or pick a faster provider in Settings" (+ an output-tab hint).
  • It can't break errors.test.js — the new kind matches a specific timed out after Ns phrase, so "Failed to fetch" etc. still classify as network.

Also: un-reds CI

The time-flaky maintenance.test.js (which was failing on main since the date rolled over) is fixed by pinning the clock with vi.setSystemTime. So this branch lands on green CI rather than inheriting the pre-existing red.

Test plan

  • npx vitest run713 passing (was 711/712 with the flake; +1 new timeout-kind test)
  • node --check on all 4 edited source files
  • Re-scan a repo live and confirm a slow/stalled provider now surfaces a Retry within ~60s instead of the 90s generic timeout

Note

This is the issue the user hit live (the output-tab.js:127 error). Doesn't change the serial-queue throughput (a separate audit finding) — but it kills the indefinite hang failure mode.

🤖 Generated with Claude Code

…hang)

A stalled provider connection had no escape — every fetch() in the AI path
lacked an AbortController, so one stuck request froze the *serialized* scan
until the output tab's generic 90s "Analysis timed out" fired
(output-tab.js:127, which is what users were hitting).

- fetchWithTimeout() now wraps all 8 provider fetch sites with a 60s
  AbortController timeout (well under the 90s tab deadline).
- New non-retryable `timeout` error kind: a stall falls straight through to
  the next provider in the attempt plan instead of re-hammering the stalled
  one, and surfaces an actionable "took too long — Retry / pick a faster
  provider" message (errors.js + an output-tab hint).

Also fixes the time-flaky maintenance test that was reddening CI on main
(pin the clock with vi.setSystemTime), so this branch lands green.

713 tests pass.
@New1Direction New1Direction merged commit 5140353 into main Jun 15, 2026
1 check passed
@New1Direction New1Direction deleted the fix/scan-timeout branch June 15, 2026 02:03
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