fix(gateway): default request_overrides to {} to avoid NoneType crash - #7291
Closed
xiaoyuervae wants to merge 1 commit into
Closed
fix(gateway): default request_overrides to {} to avoid NoneType crash#7291xiaoyuervae wants to merge 1 commit into
xiaoyuervae wants to merge 1 commit into
Conversation
When the gateway reuses a cached agent across turns, it directly assigns
`agent.request_overrides = turn_route.get("request_overrides")`.
`dict.get()` returns `None` when the key is absent, so `request_overrides`
becomes `None` on the agent instance. Every subsequent turn then fails
inside `_build_api_kwargs` at:
fast_mode=self.request_overrides.get("speed") == "fast",
raising `AttributeError: 'NoneType' object has no attribute 'get'`, which
the retry loop classifies as a non-retryable API error and fast-fails into
the fallback provider chain. In practice this manifests as every Discord
DM silently falling back from the primary model to `openai-codex` with no
HTTP request ever leaving the process — the primary model was never
actually tried.
All other call sites pass `request_overrides` through the `AIAgent`
constructor, which normalizes via `dict(request_overrides or {})` in
`run_agent.py:678`. This direct attribute assignment in `gateway/run.py`
is the only path that bypassed that normalization.
Fix: mirror the constructor's defensive default by wrapping the get() in
`or {}`.
Contributor
|
Thanks for the detailed write-up and repro steps, @xiaoyuervae! This crash was fixed on main the same day this PR was opened. Automated hermes-sweeper review.
|
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.
Summary
The gateway's per-turn agent reuse path assigns
agent.request_overrides = turn_route.get(\"request_overrides\")atgateway/run.py:6974.dict.get()returnsNonewhen the key is absent, sorequest_overridesbecomesNoneon the running agent. The next turn crashes inside_build_api_kwargsat:with
AttributeError: 'NoneType' object has no attribute 'get'.The retry loop classifies this as a non-retryable API error and fast-fails into the fallback provider chain, so in practice every gateway turn silently falls back from the primary model to the first fallback (e.g. `openai-codex`) without ever issuing an HTTP request to the primary provider. The primary model is never actually tried.
Root cause
All 7 other call sites pass
request_overridesthrough theAIAgentconstructor, which normalizes the value viadict(request_overrides or {})atrun_agent.py:678. This direct attribute-assignment branch ingateway/run.pyis the only path that bypassed that normalization.Fix
One-line change — mirror the constructor's defensive default:
Reproduction (before the fix)
hermes --profile <p> gatewaywith a primary provider that does not set `request_overrides` in its turn routing (e.g. a basic Discord DM flow through a custom provider).After applying the fix, the primary model is invoked normally.
Test plan