Expected a base64-encoded data URL with an image MIME type

Open 💬 2 comments Opened Jul 10, 2026 by MeijeSibbel

What version of Codex CLI is running?

codex-cli 0.144.0

What subscription do you have?

Pro

Which model were you using?

ALL

What platform is your computer?

Darwin 25.4.0 arm64 arm

What terminal emulator and version are you using (if applicable)?

cmux 0.64.17

Codex doctor report

What issue are you seeing?

322 )
323 + if mask_bundle is not None:
324 + log("[stage] rsync validated structure mask bundle")
325 + self._run(
326 + self.rsync_structure_masks_cmd(spec, mask_bundle),
327 + log,
328 + timeout=7200,
329 + )
330

• Context compacted

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

• I’m resuming the A2 wiring from the reviewed core. I’ll first reconcile the branch, inbox, and reservations, then finish the mask gate test-first and send the resulting wiring commit back to CrimsonCliff for
line review.

■ {
"error": {
"message": "Invalid 'input[120].content[4].image_url'. Expected a base64-encoded data URL with an image MIME type (e.g. 'data:image/png;base64,aW1nIGJ5dGVzIGhlcmU='), but got an invalid base64-encoded
value.",
"type": "invalid_request_error",
"param": "input[120].content[4].image_url",
"code": "invalid_value"
}
}

› please continue

■ {
"error": {
"message": "Invalid 'input[120].content[4].image_url'. Expected a base64-encoded data URL with an image MIME type (e.g. 'data:image/png;base64,aW1nIGJ5dGVzIGhlcmU='), but got an invalid base64-encoded
value.",
"type": "invalid_request_error",
"param": "input[120].content[4].image_url",
"code": "invalid_value"
}
}

› check

■ {
"error": {
"message": "Invalid 'input[120].content[4].image_url'. Expected a base64-encoded data URL with an image MIME type (e.g. 'data:image/png;base64,aW1nIGJ5dGVzIGhlcmU='), but got an invalid base64-encoded
value.",
"type": "invalid_request_error",
"param": "input[120].content[4].image_url",
"code": "invalid_value"
}
}

• Feedback uploaded. Please open an issue using the following URL:

https://github.com/openai/codex/issues/new?template=3-cli.yml&steps=Uploaded%20thread:%20019f0b31-3619-7b21-afdc-6e9945aab48b

Or mention your thread ID 019f0b31-3619-7b21-afdc-6e9945aab48b in an existing issue.

› codex --version

■ {
"error": {
"message": "Invalid 'input[120].content[4].image_url'. Expected a base64-encoded data URL with an image MIME type (e.g. 'data:image/png;base64,aW1nIGJ5dGVzIGhlcmU='), but got an invalid base64-encoded
value.",
"type": "invalid_request_error",
"param": "input[120].content[4].image_url",
"code": "invalid_value"
}
}

› codex doctor --json

■ {
"error": {
"message": "Invalid 'input[120].content[4].image_url'. Expected a base64-encoded data URL with an image MIME type (e.g. 'data:image/png;base64,aW1nIGJ5dGVzIGhlcmU='), but got an invalid base64-encoded
value.",
"type": "invalid_request_error",
"param": "input[120].content[4].image_url",
"code": "invalid_value"
}
}

› Improve documentation in @filename

gpt-5.6-sol ultra · ~

What steps can reproduce the bug?

Uploaded thread: 019f0b31-3619-7b21-afdc-6e9945aab48b

What is the expected behavior?

_No response_

Additional information

_No response_

View original on GitHub ↗

2 Comments

MeijeSibbel · 1 month ago

Local follow-up with the persisted thread and client logs:

  • The failing request was x-oai-request-id: 644d630c-1db2-4a29-888c-b130d913b5eb at 2026-07-10 23:19:22 UTC (HTTP 400).
  • The rejected input[120].content[4].image_url maps (after the two prepended instruction inputs) to compacted.payload.replacement_history[118].content[4], the second of three screenshots in an older user message.
  • That persisted value is not corrupt. It is a data:image/png;base64,... URL of 1,179,234 characters. Strict standard Base64 decoding succeeds and yields an 884,409-byte, 1421×748 PNG. All 58 PNG chunk CRCs validate, it has a clean IEND with no trailing bytes, and its raw SHA-256 is b3a569125b450614fd13d3f4b8862f9ec0d64191c3da0c0615b53405b1abc647.
  • The failure began immediately after compaction/resume and every later plain-text prompt rejected the same historical slot.
  • The rollout is 990,360,086 bytes. It contains 70 compaction records totaling ~862 MB because historical inline screenshots are re-embedded. The latest compaction record alone is 16,668,195 bytes and retains 20 inline PNG data URLs totaling 16,484,276 characters.
  • The still-running resumed process was CLI 0.142.2; the machine had subsequently been upgraded, which explains why the issue form reported 0.144.0.

Source-level follow-up:

  • The index offset is explained by Responses Lite prepending two request items, so persisted history item 118 becomes API input 120 (client.rs).
  • Remote compaction preserves retained InputImage data while counting each image as zero tokens during retained-history truncation, then installs that replacement history (compact_remote_v2.rs, install path). Current main still has this behavior.
  • I found no client-side truncation or malformed-base64 serialization path: the replayed URL is cloned, the optional detail field is removed for Responses Lite, and the request is serialized as one body.
  • The rejected screenshot is retained image #19. Cumulative decoded image bytes are 9,958,609 before it and 10,843,018 through it, making it the first image to cross both 10 MB and 10 MiB. An internal replay/validator boundary around 10 MiB is therefore a strong lead, but remains an inference rather than a proven limit.

The evidence now points most strongly to image-heavy full-history replay hitting an undocumented backend validation/size pathology, not a corrupt original attachment. Starting a new thread and recovering the handoff externally works. A manual recovery would need to back up the rollout and replace all input_image items in only the newest compacted replacement history with text placeholders; removing only the reported image may simply move the error to the next retained image.

MeijeSibbel · 1 month ago

One additional source-level detail from the exact failing Codex CLI 0.142.2 tag: centralized image preparation was already always-on, but it did not bound cumulative retained-image bytes. High/Auto only resized images above 2048 px or 2,500 32px patches. The rejected PNG was 1421×748 (1,080 patches, 884,409 bytes), so it was preserved byte-for-byte. Remote compaction then counted InputImage as zero text tokens and retained it unchanged.

This connects the failure to #23257 and #30441, but the boundary differs from #30441’s proposed 10 MiB per-image cap: every image here was individually valid and under 1 MiB. The reported item was simply the first historical image that took cumulative decoded retained images past the request budget, which was then surfaced misleadingly as invalid Base64.

A useful regression test would compact and resume a history containing many individually valid, sub-limit PNGs whose cumulative bytes exceed the request budget. The durable fix needs a cumulative image byte/count/age budget—or historical-image placeholders/out-of-line blobs—during compaction and resume, rather than only per-image resizing.