fix(gateway): classify transient provider-resolution errors and label fallback by config provider - #32881
Conversation
… fallback by config provider
45d597f to
4542250
Compare
|
Rebased onto current The conflict was confined to this PR's two files. Note for review: upstream landed an overlapping interim fix in
|
|
Closing — superseded by the consolidated #46643, which folds this PR's change in alongside the related work on the same issue. Reopen if that's not right. |
What does this PR do?
When the primary provider's credential resolution fails,
gateway.run._resolve_runtime_agent_kwargscaught everyAuthErrorand logged it asPrimary provider auth failed: ... — trying fallback. That wording is correct for a genuine credential problem (expired/revoked/missing token), butAuthErroralso carries transient upstream failures — a 429 usage-limit / rate-limit or a 5xx that a perfectly valid credential simply hit. Those carryrelogin_required=False, yet were still surfaced as "auth failed", driving operators to re-runhermes authon tokens that are actually fine (issue #32790, surface #2).This branches the warning wording on the structured
relogin_requiredhint theAuthErroralready exposes, so transient conditions log asPrimary provider unavailable (transient/rate-limit): ...while real credential failures keep the re-auth wording.It also fixes the
Fallback provider resolved:log line (issue #32790, surface #4): it printedruntime.get("provider"), the normalized internal runtime category, so anollamafallback was mislabeled asopenroutereven though traffic correctly hit the configured endpoint. It now reports the literalproviderkey from config (entry.get("provider")).Scope note: the issue's most alarming surface (#1, the chat reply literally reading
No Codex credentials stored) corresponds to a genuinely-missing-credentialsAuthError(code=codex_auth_missing,relogin_required=True). The current credential-pool and token-refresh paths already classify a 429 distinctly from missing credentials (1-hour cooldown viaEXHAUSTED_TTL_429_SECONDS, and codex tokens are only cleared on terminal refresh errors — not on a 429), so that exact string is not reproducible from a quota event againstmain. Confirming and fixing that surface needs the reporter's full traceback, so this PR usesRefsrather thanFixes.Related Issue
Refs #32790
(Partial: addresses the gateway-log and fallback-resolution-label surfaces; the chat-reply root cause is deferred pending the reporter's traceback — see scope note above.)
Type of Change
Changes Made
gateway/run.py: in_resolve_runtime_agent_kwargs, branch the warning log onAuthError.relogin_requiredso transient (429/5xx) failures are not labeled "auth failed".gateway/run.py: in_try_resolve_fallback_provider, log the configuredentry.get("provider")on fallback resolution instead of the normalizedruntime.get("provider")category.tests/gateway/test_auth_fallback.py: addTestProviderErrorClassificationcovering (a) a transient 429 AuthError logging as transient, (b) a genuine credential AuthError still logging as auth-failed, (c) the fallback log namingollamanotopenrouter.How to Test
pytest tests/gateway/test_auth_fallback.py -q— 6 passed (3 existing + 3 new).model.provider: openai-codexwith a valid OAuth credential and anollamafallback, then induce a token-refresh 429. The gateway log now readsPrimary provider unavailable (transient/rate-limit): ... — trying fallbackandFallback provider resolved: ollama model=<X>.Primary provider auth failed: ..., preserving the re-auth guidance.Platforms tested on: macOS (darwin-arm64), local —
pytest tests/gateway/test_auth_fallback.py, plustests/test_empty_model_fallback.pyandtests/run_agent/test_provider_fallback.py(40 passed). Change is pure log-string/branching with no platform-specific APIs; Linux/Windows/WSL2 covered by CI.Checklist
Code
fix(scope):,feat(scope):, etc.)pytestsuites and they passDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/A