fix: ingest hang diagnostics — timeout detection + actionable error output#3
Merged
1a35e1 merged 1 commit into1a35e1:mainfrom Feb 23, 2026
Merged
Conversation
…ands The root problem: fetch() has no built-in timeout. If the Sonar server accepts a TCP connection but stalls before sending a response the spinner renders indefinitely and the process must be killed manually. Changes: src/lib/client.ts - gql() now wraps every request in an AbortController with a configurable timeoutMs (default 20 s). AbortError is caught and rethrown as a human- readable message that names the timeout, explains the likely cause, and directs the operator to check SONAR_API_URL and retry. src/commands/ingest/tweets.tsx src/commands/ingest/bookmarks.tsx - Added a component-level 15 s wall-clock deadline (useRef + setTimeout) that fires independently of the fetch timeout. This catches the edge case where the request itself times out inside the gql() call but React has not yet had a chance to surface the error. - Timeout state is tracked separately so the UI can render a yellow warning (rather than a red error) with a note to run 'sonar ingest monitor' — the server may have queued the job even if the response was lost. - When the mutation returns false (job not queued) a follow-up hint directs the operator to check their account status. src/commands/monitor.tsx - The raw fetch() call for /indexing/status now uses its own AbortController (10 s). In --watch mode this prevents a single hung poll from freezing the entire watch loop.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord. Comment |
1a35e1
approved these changes
Feb 23, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bug
sonar ingest tweetsandsonar ingest bookmarksspin the loading indicator indefinitely when the Sonar server accepts the TCP connection but stalls before completing the response (e.g. under high load, misrouted traffic, or a cold-start delay). The only recovery isCtrl+C. There is no feedback about what went wrong or what to try next.The same silent-hang issue affects
sonar ingest monitor --watch, where a single stalled poll freezes the entire watch loop.Root cause
gql()insrc/lib/client.tspasses nosignaltofetch(), so requests have no timeout. Node's default TCP timeout is effectively infinite for established connections.Fix
src/lib/client.tsAbortControllerwith a configurabletimeoutMs(default 20 s).AbortErroris caught and rethrown as a structured message that names the elapsed timeout, attributes the likely cause, and directs the operator to checkSONAR_API_URLand retry.src/commands/ingest/tweets.tsx+bookmarks.tsxuseRef/setTimeout) fires independently of the HTTP-layer timeout. This closes the gap where thegql()call times out but React hasn't surfaced the error yet.sonar ingest monitor— the server may have queued the job even if the response was lost.false(job explicitly not queued), a follow-up hint directs the operator tosonar account.src/commands/monitor.tsxfetch()call for/indexing/statusnow carries its ownAbortController(10 s). In--watchmode a single stalled poll no longer freezes subsequent polls.Verification
Reproduce the hang by pointing
SONAR_API_URLat a server that accepts the connection but never responds (e.g.nc -l 9999):