diff --git a/docs/architecture/RESILIENCE_GUIDE.md b/docs/architecture/RESILIENCE_GUIDE.md index d946513afb..5aaba73652 100644 --- a/docs/architecture/RESILIENCE_GUIDE.md +++ b/docs/architecture/RESILIENCE_GUIDE.md @@ -308,10 +308,13 @@ event. per-provider list of rules (`{id, fromStatuses, toStatus, textMarkers, excludeMarkers, defaultRetryAfterMs}`), matched via `applyStatusRestatement()`. - Call site: the `providerFailure:` block in `open-sse/handlers/chatCore.ts` - (around line 3654), right after the upstream error is parsed — both the - HTTP-error path and the error-hidden-in-a-200-SSE-stream path converge - there before `applyStatusRestatement()` runs, so every downstream consumer - sees the corrected status. + (around line 3654), right after `parseUpstreamError()` parses an upstream + response with an error HTTP status (`!providerResponse.ok`), and before any + classification runs, so every downstream consumer sees the corrected + status. Errors embedded inside a `200` SSE stream follow a separate, + later stream-parsing path and are **not** covered by this hook today — a + known limitation, not yet needed for agentrouter's misstatus (which + surfaces as an error HTTP status). - Retry eligibility: `429` is in `RETRY_AFTER_ELIGIBLE_STATUSES` (`open-sse/services/combo/unavailableRetryGate.ts`), so a restated error carries a real retry window instead of surfacing as a dead `403`. diff --git a/open-sse/config/upstreamStatusRestatement.ts b/open-sse/config/upstreamStatusRestatement.ts index af27c2cd81..75f84ecf72 100644 --- a/open-sse/config/upstreamStatusRestatement.ts +++ b/open-sse/config/upstreamStatusRestatement.ts @@ -8,11 +8,15 @@ * fallback engine classifies it as AUTH_ERROR instead of a quota event. * * applyStatusRestatement() is called from exactly ONE place — the - * `providerFailure:` block in open-sse/handlers/chatCore.ts, right after the - * upstream error is parsed (both the HTTP-error path and the error-hidden-in- - * a-200-SSE-stream path converge there) — so every downstream consumer - * (checkFallbackError, combo aggregation, the client response) sees the - * corrected status. 429 is Retry-After-eligible in + * `providerFailure:` block in open-sse/handlers/chatCore.ts, right after + * parseUpstreamError() parses an upstream response with an error HTTP status + * (!providerResponse.ok), and before any classification runs — so every + * downstream consumer (checkFallbackError, combo aggregation, the client + * response) sees the corrected status. Errors embedded inside a 200 SSE + * stream follow a separate, later stream-parsing path and are NOT covered by + * this hook today (known limitation; not yet needed for agentrouter's + * misstatus, which surfaces as an error HTTP status). 429 is + * Retry-After-eligible in * open-sse/services/combo/unavailableRetryGate.ts, so the client also gets a * retry window instead of a dead 403. *