Repository navigation
Conversation
Collaborator
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.
What does this PR do?
The gateway's connection-error reply previously collapsed three different failures into one
"endpoint is not running or is unreachable" message:
httpx.ReadError: [Errno 104] Connection reset by peer) — says nothing about whether the endpoint is up; an earlier call in the same turn mayalready have been answered by it ([Bug] Connection reset by peer (errno 104) with Ollama local endpoint — 76KB payload rejected #26339),
connection refused/[Errno 111]/[WinError 10061]/no route to host) — the case the [Bug]: Local model server connection errors fall through to unhelpful generic chat reply #86570 wording was written for,
openai.APIConnectionError: Connection error.— the SDK flattenedthe cause away, so neither diagnosis is supported.
This PR splits the single connection row in
_PROVIDER_ERROR_REPLIESinto three: interrupted,unreachable, and a catch-all ambiguous reply that explicitly names both possibilities and never
claims the endpoint is down. It also removes the optional
apiprefix from the genericconnection error|timeoutmarker so an SDK class name likeAPIConnectionErrorno longermatches the generic "connection error" phrase and falls into the wrong category.
The actionable guidance is preserved: every reply still names a slash command (
/retry) andhermes doctor, and auth/policy/rate-limit precedence is unchanged (rate-limit > auth > policyRelated Issue
Fixes #116323
Related: #109701 (open, CONFLICTING) covers the same classification split but does not retain
the #111600 reply contract and newer auth/quota tests; this PR keeps that contract.
Type of Change
Changes Made
gateway/run.py: add_CONNECTION_INTERRUPTED_MARKERS/_GATEWAY_CONNECTION_INTERRUPTED_REand
_ENDPOINT_UNREACHABLE_MARKERS/_GATEWAY_ENDPOINT_UNREACHABLE_RE; add two new rows to_PROVIDER_ERROR_REPLIES(interrupted, unreachable) and reword the existing catch-all row toan ambiguous reply that does not claim the endpoint is down; drop the
(?:api\s*)?prefixfrom the generic
connection error|timeoutmarker in_CONNECTION_ERROR_MARKERSand from theunreachable set so
APIConnectionErroris not classified as "unreachable"; anchor theerrno 104/errno 111/winerror 10061numeric markers with word boundaries so a longererror code (e.g.
Errno 1043) does not false-positive into a connection category.tests/gateway/test_local_model_connection_reply.py: addINTERRUPTED_ENVELOPES,UNREACHABLE_ENVELOPES,AMBIGUOUS_ENVELOPES; addtest_three_connection_causes_are_three_ distinct_categoriesandtest_interrupted_connection_delivery_keeps_precedence_and_redaction(rides
_sanitize_gateway_final_responseon telegram/slack/feishu, checks precedence withtainted 401/400/429 + reset envelopes and redaction); remove the now-invalid assertion that a
bare
openai.APIConnectionError(no provider-failure envelope prefix) is a provider error.How to Test
All 152 tests pass with the fix (including the word-boundary anchors), and the 4 new regression
tests fail on the pre-fix code (verified by reverting
gateway/run.pytoorigin/mainandre-running).
Checklist
Code
fix(scope):, etc.)scripts/run_tests.shon the touched suites and all tests passDocumentation & Housekeeping
cli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AExclusions (left for follow-ups, issue stays open)
connection error|timeoutmarker'sapiprefix — rejected: it madeAPIConnectionError(an SDK class name) match the generic phrase and fall into the wrongcategory; dropping it is the root-cause fix.
catch-all row already says "either interrupted or unreachable" and never claims the endpoint
is down; a third distinct reply would add wording churn without a behavior change.
message-classification defect, not a retry-policy change (see [Bug]: v0.20.6 Discord Gateway long sessions hit pre-stream Codex ReadError timeouts #103673 / fix(codex): pre-stream connect/receive failures reconnect once in place before the outer retry loop sees them (#103673, salvage #103685) #115806 for the
pre-stream retry work).