Skip to content

fix(scanner,reporter): Longer inference timeout, retry Sentry reporting drops - #21

Merged
ryan953 merged 3 commits into
mainfrom
reliability-retries
Aug 12, 2026
Merged

fix(scanner,reporter): Longer inference timeout, retry Sentry reporting drops#21
ryan953 merged 3 commits into
mainfrom
reliability-retries

Conversation

@ryan953

@ryan953 ryan953 commented Aug 12, 2026

Copy link
Copy Markdown
Member

The last two getsentry/sentry scheduled runs went red for two different,
unrelated transient reasons after their actual bugs were fixed — an LLM
inference timeout on one pattern, and a single dropped Sentry event out of
2887 on the reporting side. Neither indicated a real problem in the repo
being scanned.

Inference timeout: raises analyzeWithClaude's request timeout from 120s
to 240s. The one failure observed (no-class-components in
getsentry/sentry, run
31643785552)
aborted at exactly the old 120s ceiling — evidence of a slow request under
load, not a hung one — so headroom is the narrower fix; a retry loop would
have been more machinery than the evidence justified. Also fixes a latent bug
where AbortSignal.timeout()'s DOMException doesn't extend Error, so the
intended "OpenRouter request timed out after Nms" message was silently
skipped in favor of the generic "operation was aborted due to timeout".

Sentry reporting drops: this one keeps its retry logic rather than a
simpler tolerance threshold, deliberately — sentry.ts's existing comments
show PR #15 hardened this exact path specifically to eliminate silent data
loss ("a throttled run reports 'success' while data never reached Sentry"),
and tolerating a few dropped events would reintroduce that. FindingReporter
now retries a batch up to REFACTOR_TASKS_SENTRY_SEND_ATTEMPTS times
(default 3) when the transport records a new drop (e.g. network_error)
since that attempt started, instead of failing the run on the very first
drop regardless of cause. Only drops that survive every attempt fail the
run — verified against both an unreachable endpoint (retries exhaust, run
fails loud with the attempt count) and a local server that fails once then
recovers (retries succeed, run passes). Resending re-reports the whole batch,
including already-delivered findings; duplicates land as repeat occurrences
of the same fingerprinted issue, not separate ones.

Refs the two post-fix CI runs this responds to:
31642621319
(dropped Sentry event) and
31643785552
(inference timeout on no-class-components).

A single OpenRouter request timeout or transient provider error used to fail the whole pattern immediately, which — since scan-and-report treats any failed pattern as fatal — took the entire CI run down with it. analyzeWithClaude now retries the inference call plus response parsing up to 3 times with backoff before giving up, via a small shared withRetry() helper that logs each failed attempt so a recovered blip still leaves a trace.

Also fixes a latent bug in the OpenRouter provider's timeout handling: AbortSignal.timeout() aborts with a DOMException, which does not extend Error, so the 'err instanceof Error' check silently skipped the intended wrapped message ('OpenRouter request timed out after Nms') and let the generic 'operation was aborted due to timeout' through instead.

Refs https://github.com/getsentry/sentry/actions/runs/31643785552, where no-class-components timed out after exactly 120s with no retry.
assertNoDrops() failed the whole run on any transport-recorded drop, including a single one-off network_error out of thousands of events — e.g. a run reporting 2887 findings failed because 1 send hit a transient connection error, even though every other event was delivered.

sendItems() now retries a chunk (or single-batch window) up to REFACTOR_TASKS_SENTRY_SEND_ATTEMPTS times (default 3) when the transport records new drops since the attempt started, logging each retry. Resending re-reports every finding in the batch; duplicates land as repeat occurrences of the same fingerprinted Sentry issue, not separate issues. Only drops that survive every attempt (unrecoveredDrops) fail the run — the transport's raw cumulative tally can't tell a recovered drop from a real one, so assertNoDrops() no longer reads it directly.

Verified against a real ECONNREFUSED endpoint (retries exhaust, run fails loud with the attempt count in the message) and a flaky local server that fails once then succeeds (recovers on retry, run succeeds) — both reproduce the getsentry/sentry run's 'Sentry dropped 1 of 2887 events (network_error=1)' failure and its fix.

Refs https://github.com/getsentry/sentry/actions/runs/31642621319
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


Bug Fixes 🐛

  • (scanner,reporter) Longer inference timeout, retry Sentry reporting drops by ryan953 in #21

🤖 This preview updates automatically when you update the PR.

Replaces the withRetry() wrapper (and its now-unused utils/retry.ts) around analyzeWithClaude with a simpler fix: raise timeoutMs from 120s to 240s. The one failure we've observed (no-class-components in getsentry/sentry, run 31643785552) aborted at exactly the old 120s ceiling, which looks like a slow request under load rather than a hung one — headroom is the narrower fix for that evidence, and the retry wrapper was more machinery than the observed failure mode justified.

The OpenRouter timeout-message classification fix (DOMException doesn't extend Error) stays: it's independently useful for whatever timeout duration is configured.
@ryan953 ryan953 changed the title fix(scanner,reporter): Retry transient inference/reporting failures fix(scanner,reporter): Longer inference timeout, retry Sentry reporting drops Aug 12, 2026
@ryan953
ryan953 marked this pull request as ready for review August 12, 2026 22:28
@ryan953
ryan953 merged commit 64f45ee into main Aug 12, 2026
13 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