Codex Desktop can crash or freeze when opening image-heavy sessions because session JSONL embeds base64 image payloads

Open 💬 3 comments Opened Jun 16, 2026 by Howard0401

What version of the Codex App are you using (From “About Codex” dialog)?

26.609.71450

What subscription do you have?

Business, pro

What platform is your computer?

Windows 11

What issue are you seeing?

Summary

Codex Desktop can crash in the Electron main process, or stall the desktop while
loading, when opening a session whose JSONL transcript contains many embedded
image/base64 payloads. The immediate failure observed was
RangeError: Invalid string length inside a main-process stdout/IPC write path,
but the root cause appears to be unbounded session JSON/stdout/IPC payload
construction for records that include large data:image/...base64 strings and
image generation results.

Environment

  • App: Codex Desktop
  • Platform: Windows 11
  • Package version observed in stack trace: OpenAI.Codex_26.609.9530.0_x64__2p2nqsd0c76g0

What steps can reproduce the bug?

Crash

A JavaScript error occurred in the main process

Uncaught Exception:
RangeError: Invalid string length
    at JP.write (...OpenAI.Codex_26.609.9530.0_x64__2p2nqsd0c76g0\app\res...:21)
    at Socket.onStdoutData (...)
    at Socket.emit (node:events:508:28)
    at addChunk (node:internal/streams/readable:563:12)
    at readableAddChunkPushByteMode (node:internal/streams/readable:514:3)
    at Readable.push (node:internal/streams/readable:394:5)
    at Pipe.onStreamRead (node:internal/stream_base_commons:189:23)

Local Evidence

One affected local transcript had the following properties before repair:

  • JSONL size: about 2.49 GB
  • Line count: about 12k
  • Largest single JSONL record: about 6 MB
  • Image/base64 related records:
  • thousands of data:image/...base64 occurrences in tool output records
  • hundreds of image_generation_end events with multi-megabyte base64 result payloads

An image-only local repair externalized embedded image data and reduced that
transcript to about 25 MB while preserving parseable JSONL, prompts, text
outputs, and normal context.

Representative oversized record shape:

{
  "type": "response_item",
  "payload": {
    "type": "function_call_output",
    "output": [
      {
        "type": "input_image",
        "image_url": "data:image/png;base64,..."
      }
    ]
  }
}

Image generation events also store large payloads under fields like:

{
  "type": "response_item",
  "payload": {
    "type": "image_generation_end",
    "result": "<multi-megabyte base64 image>"
  }
}

What is the expected behavior?

Expected Behavior

Opening a previous session should not require materializing all historical
binary/image payloads as one giant JSON/stdout/IPC string. Image-heavy sessions
should remain navigable, with image artifacts loaded lazily or represented by
metadata until explicitly opened.

Actual Behavior

Opening the affected session caused Codex Desktop to crash in the Electron main
process with RangeError: Invalid string length. In related cases, app startup
and session list loading can also become visibly sluggish when the local Codex
state contains multi-GB JSONL/SQLite/session backup data.

In the same local state, after image payload repair, the remaining startup
stutter was correlated with text-heavy session JSONL files around 100-250 MB
each and a multi-GB local log SQLite database. Those files did not contain image
base64 and therefore could not be fixed by image externalization alone. This
points to a broader reader/indexing problem: startup and session list rendering
should not synchronously scan or materialize large historical transcripts or log
stores.

Moving those active session JSONL files out of .codex/sessions is not an
acceptable user-facing workaround for people who rely on the Codex Desktop GUI
as their preserved conversation archive, because it hides conversations from the
sidebar. The fix needs to preserve GUI discoverability while making loading lazy
and bounded.

Proposed Fix

This should be fixed at the session JSON I/O boundary, not only in the renderer UI.

1. Writer-side payload externalization

Do not write data:image/...base64 strings or raw binary-like blobs into session
JSONL. Store image/blob bytes in an artifact store such as a content-addressed
blob directory, and keep JSONL bounded:

{
  "type": "artifact_ref",
  "artifact_id": "sha256-or-uuid",
  "path": "session-artifacts/<thread>/<artifact>.png",
  "mime": "image/png",
  "bytes": 2751234,
  "width": 2048,
  "height": 1152
}

If existing schemas require a string field such as image_url, store a bounded
artifact URI string and maintain a sidecar mapper:

{
  "image_url": "codex-artifact://session-payloads/<thread>/<sha256>.png"
}

2. Reader-side lazy loading and pagination

  • Load session JSONL incrementally.
  • Do not materialize the entire transcript and all image payloads in one string.
  • Elide any single event above a conservative byte threshold.
  • Paginate large tool outputs and old image events.
  • Teach image generation result readers to accept artifact refs, not only raw base64.
  • Build the session list from a compact index rather than reading large JSONL

transcripts during startup.

  • Rotate or compact large local log SQLite stores so startup does not depend on

opening a multi-GB database.

Compatibility note: replacing image_generation_end.payload.result with an
artifact URI in current Codex Desktop builds can cause Invalid image generation
result base64
, because that field is still interpreted as raw base64. Until
renderer support exists, the reader should render a bounded placeholder instead
of sending an artifact URI to a base64 decoder.

3. IPC/stdout hard limits

Add a hard byte cap before main-process stdout/IPC response construction. If a
response exceeds the cap, return a structured truncation record instead of
attempting to allocate a huge string.

4. Migration/repair

On session open or background maintenance:

  • detect legacy transcripts containing large data:image/ strings or raw image base64,
  • move blobs to artifact storage,
  • replace inline image fields with bounded refs or explicit placeholders,
  • preserve the original transcript in a backup location.

Why UI-only truncation is insufficient

The crash happens before a usable UI recovery path: the main process is already
trying to serialize/write oversized data. Renderer-side "show less" behavior
does not protect against unbounded main-process JSON/stdout/IPC writes.

Additional information

Suggested Regression Test

Create a fixture session JSONL containing hundreds of image records with 2-6 MB
base64 payloads. Opening the session should:

  • not crash the Electron main process,
  • keep peak memory bounded,
  • show metadata/placeholders for old image payloads,
  • allow explicit lazy loading of individual artifacts,
  • preserve parseable session history.

Here are my local solution FYI, but I just would like to get the codex runtime fix solution.

https://github.com/Howard0401/codex-session-json-io-guard/tree/main

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗