Codex Desktop can crash or freeze when opening image-heavy sessions because session JSONL embeds base64 image payloads
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 wasRangeError: 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/...base64occurrences in tool output records - hundreds of
image_generation_endevents 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, because that field is still interpreted as raw base64. Until
result base64
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
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗