fix(agent): catch ChatGPT-account Codex data-URL rejection so images are stripped instead of cascading to compression#23602
Merged
Merged
Conversation
…are stripped instead of cascading to compression When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue #23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs #23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
Contributor
🔎 Lint report:
|
1 task
rmulligan
pushed a commit
to rmulligan/hermes-agent
that referenced
this pull request
May 11, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
JinyuID
pushed a commit
to JinyuID/hermes-agent
that referenced
this pull request
May 11, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
jsboige
pushed a commit
to jsboige/hermes-agent
that referenced
this pull request
May 14, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
heybenn42
pushed a commit
to heybenn42/hermes-agent
that referenced
this pull request
May 15, 2026
* upstream/main: (1099 commits) chore: ruff auto-fix C401, C416, C408, PLR1722 (NousResearch#23940) feat(prompt-cache): cross-session 1h prefix cache for Claude on Anthropic / OpenRouter / Nous Portal (NousResearch#23828) chore: ruff auto-fix PLR6201 — tuple → set in membership tests (NousResearch#23937) chore(release): add AUTHOR_MAP entry for wuli666 fix(auxiliary): evict async wrappers on poisoned client (follow-up to NousResearch#23482) fix(cli,tui): align CJK / wide-char markdown tables (NousResearch#23863) chore: ruff auto-fixes — collapsible-else-if, if-stmt-min-max, dict.fromkeys (NousResearch#23926) fix(/model): surface Nous Portal models from remote catalog manifest (NousResearch#23912) fix(cli): defensive _slash_confirm_state access + AUTHOR_MAP fix: use TUI modal for slash confirmations rebuild model catalog fix(dashboard): validate dist exists when --skip-build is set fix(dashboard): fallback to stale dist, retry build, add --skip-build flag chore: AUTHOR_MAP entry for VinceZcrikl noreply (NousResearch#23647) fix: make web UI build output decoding robust on Windows fix(agent): catch ChatGPT-account Codex data-URL rejection so images are stripped instead of cascading to compression (NousResearch#23602) revert: roll back /goal checklist + /subgoal feature stack (NousResearch#23813) chore: AUTHOR_MAP entries for sudo-hardening salvage contributors fix(approval): catch sudo with stdin/askpass/shell privilege flags fix(terminal): block sudo -S password guessing when SUDO_PASSWORD is not set ...
AlexFoxD
pushed a commit
to AlexFoxD/hermes-agent
that referenced
this pull request
May 21, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
…are stripped instead of cascading to compression (NousResearch#23602) When the user's main provider is openai-codex on the ChatGPT-account backend (https://chatgpt.com/backend-api/codex), sending a native image attachment encodes it as data:image/...base64,... in the input_image field. The OpenAI Responses API on the public endpoint accepts that, but the ChatGPT-account variant rejects it with HTTP 400: Invalid 'input[N].content[K].image_url'. Expected a valid URL, but got a value with an invalid format. Hermes' image-rejection phrase list didn't include this wording, so the error escaped the strip-and-retry branch and fell through to the generic recovery path: model fallback → context-too-large → compression cascade → auxiliary OpenRouter 402 spam (issue NousResearch#23570). Add a NARROW phrase keyed on the field-path apostrophe used by the Codex Responses error format: "image_url'. expected". This matches the actual error format without false-tripping on generic 'Expected a valid URL' errors from unrelated tools (webhooks, redirect_uri, etc.). Once matched, the existing branch strips images from history, sets _vision_supported= False for the session, and retries text-only. Refs NousResearch#23570 (1 of 3 image-replay improvements; persistence rewrite to store image PATHS instead of inlined base64 is a separate follow-up)
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.
Closes part of #23570 (image-rejection cascade on Codex ChatGPT-account backend).
Summary
ChatGPT-account Codex (
https://chatgpt.com/backend-api/codex) rejectsdata:image/...base64URLs ininput_imagefields with HTTP 400 "Invalid 'input[N].content[K].image_url'. Expected a valid URL." Hermes' phrase list didn't recognize this wording, so the error escaped the strip-and-retry branch and cascaded into compression / context-too-large recovery — which on a depleted-OpenRouter setup turned into the 402 storm in #23570.Changes
run_agent.py: added one narrow phrase"image_url'. expected"to_IMAGE_REJECTION_PHRASES. Match is keyed on the field-path apostrophe so it doesn't false-trip on generic "Expected a valid URL" errors from unrelated tools (webhooks, redirect_uri, etc.).tests/run_agent/test_image_rejection_fallback.py: added the real Codex error body to the positive-match list, plus a new test confirming non-image URL errors do NOT trip the new phrase.Validation
tests/run_agent/The 1 unrelated failure (
test_async_httpx_del_neuter::test_same_key_replaces_stale_loop_entry) reproduces on bareorigin/main— pre-existing.Scope note
This is the recovery patch — it makes the already-broken request graceful. The underlying replay-bloat issue (long sessions persist multi-MB base64 in history and re-send it every turn) is architectural and stays open. The fix there is to persist image PATHS and rebuild the data URL at API-send time. Separate PR forthcoming.
Refs #23570 (3 of 3: PR #23585 covered silent config-parse failure, PR #23597 added the auxiliary 402-unhealthy cache; this one catches the specific Codex image-rejection wording so the user's session would degrade gracefully).