Repository navigation
Unbounded image history payload can make threads unrecoverable with 413 #30441
Description
What version of Codex are you using?
Current main as of commit bdd282f in openai/codex.
What issue are you seeing?
After asking Codex to analyze an image for OCR, the thread can become permanently stuck with repeated request-size failures:
unexpected status 413 Payload Too Large: request too large, url: http://127.0.0.1:48111/v1/responses
Once the thread is in this state, sending a follow-up message still fails even when the image attachment is no longer attached to the chat. The oversized payload appears to be persisted in conversation history/rollout state and replayed on resume.
This looks related to #11440, but the concrete path here is image/tool-output history rather than only long text compaction.
Root cause hypothesis
In the current code path, image tool/function output can be prepared into a base64 data URL before being persisted into conversation history. Resume reconstruction later records persisted rollouts into history, and function output image items are preserved without counting the image URL against truncation budgets.
That means one large prepared image data URL can poison a rollout/history record and keep being included in later /v1/responses payloads.
Expected behavior
Codex should bound image payloads that enter model-visible history and should recover by replacing or omitting oversized image items, rather than replaying an unbounded base64 image until every follow-up request fails with 413.
Proposed fix
I have a patch branch here, but this repo currently blocks PR creation from non-collaborators:
Commit:
383ac91 Bound image history payloads
The patch does two things:
- Caps prepared prompt image data URLs at 10 MiB before they are persisted into conversation history, replacing oversized prepared images with the existing image-too-large placeholder.
- Counts function-call output image URLs against the existing byte/token truncation budget instead of preserving them unbounded, so resumed legacy rollouts can omit oversized image items.
Validation run on the patch branch
just fmt
just test -p codex-utils-output-truncation
just test -p codex-core image_preparation
just fix -p codex-utils-output-truncation
just fix -p codex-core
The full just test suite was not run locally.
Activity
github-actions commentedon Jun 28, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
jroth1111 commentedon Sep 11, 2026
Additional evidence relevant to the proposed per-image cap: many individually sub-10-MiB images can still exceed the aggregate request limit.
A deterministic test with real codex-cli 0.154.0 used an isolated temporary home, twelve distinct generated 1280×1280 PNGs in paired tool-call/output records, and a localhost Responses mock enforcing a 64 MiB JSON-body cap. Every encoded image was below 10 MiB, but the serialized request was 78,732,011 bytes and was rejected. A bounded recovery copy retaining the two newest images sent 13,175,417 bytes, included ten explicit references to archived originals, and completed successfully. The original rollout remained byte-for-byte unchanged. This is a client replay/transport test against a mock, not evidence of the production gateway's exact cap.
There is also an important repair compatibility constraint: newer paginated rollouts have record ordinals and persisted database byte offsets. Shrinking earlier JSONL records can invalidate those offsets. The tested recovery copy preserves the original source, response items, tool-call/output IDs, image originals and metadata; it supplies a bounded replacement checkpoint under a new conversation identity. It refuses unsupported lineage/rollback cases. This is a local workaround, not a supported native repair API.
Continued visual work subsequently regrew the affected active history to approximately 113 MiB. An offline watcher that waits for clients to close cannot prevent that active-session growth. A recovered copy was verified with a live provider turn, but sustained continuation and automatic goal-state transfer were not established.
The detailed measurements, version limitations, pagination findings, and recovery tests are maintained in this report on #41338. Please include aggregate serialized-byte preflight for both inference and compaction, plus a supported recovery path, in the fix criteria. Per-image limits alone do not bound a multi-image conversation.
Only synthetic measurements and sanitized aggregate observations are included. No private conversation IDs, paths, images, source documents, account data, credentials or raw logs are attached.
BuhtigNotes13 commentedon Oct 11, 2026
A related image-limit/recovery observation, checked in recorded task results on October 11, 2026. This differs from the HTTP 413 in the original report; a shared cause is unproven.
A long image-processing task on a connected desktop has a failed turn with HTTP 400, type
invalid_request_error, paraminput, codeimage_request_too_large: “The combined resolved image content is too large. Reduce the number or size of input images.” The visible recovery instruction already requested one-source comparisons and resized previews, but that turn did not complete. We have not measured the actual submitted image payload or established how much history was included.A limited workflow workaround worked in this case: continue the work in a separate task using five-source allocations. That task's completed state was verified, and its output reports completed image batches. This did not repair the original task, and five images is not a measured or generally safe capacity limit; image sizes and accumulated history may differ. We have not verified whether the separate task inherited any earlier image history. App and OS versions were not recorded for this observation.
The size rejection itself may be an expected input limit. The useful recovery question is whether the product can provide a supported way to reduce resolved image input in an existing task and continue it without editing internal history files. No community code was run or device settings changed for this report. No private images, paths, task IDs or raw transcripts are attached. Prepared with AI assistance.