Codex session replay can fail with invalid_encrypted_content from persisted encrypted reasoning/compaction records
Summary
A Codex CLI session under a local repo became impossible to continue because the API rejected persisted encrypted reasoning content during conversation replay:
{
"type": "error",
"error": {
"type": "invalid_request_error",
"code": "invalid_encrypted_content",
"message": "The encrypted content gAAA... could not be verified. Reason: Encrypted content could not be decrypted or parsed."
},
"status": 400
}
The user-visible conversation messages were still present locally, but replay failed before the agent could continue.
Environment
- Codex CLI:
codex-cli 0.135.0 - Install method: npm package
@openai/codex - Package repository metadata:
git+https://github.com/openai/codex.git, directorycodex-cli - OS: Red Hat Enterprise Linux 9.4 x86_64
- Auth mode: ChatGPT tokens
- Session file pattern:
$CODEX_HOME/sessions/YYYY/MM/DD/rollout-*.jsonl
What I found in the affected session file
The affected repo-local rollout file had a valid session_meta and most user/assistant events were intact, but it also contained corrupt replay material:
554top-levelresponse_itemrows with payloadtype: "reasoning"and anencrypted_contentfield.4nested encryptedcompactionrecords insidecompacted.payload.replacement_history.28malformed JSONL rows, including NUL-byte rows and partial/truncated JSON around the later part of the file.
After removing only those invalid/encrypted replay-only records, the session JSONL parsed again and the user-visible final turns remained available.
Expected behavior
Codex should not fail the whole continuation request when persisted local history contains encrypted reasoning or encrypted compaction blobs that the current client/server can no longer decrypt or parse.
A safer behavior would be one of:
- skip/drop invalid encrypted reasoning or compaction records during replay,
- fall back to visible
message,event_msg, and tool-output records, - detect and repair/ignore malformed JSONL rows before constructing API input,
- show a local recovery prompt instead of sending invalid encrypted content to the API.
Actual behavior
The continuation failed with invalid_encrypted_content from the API. The user had to manually sanitize the rollout JSONL file before the conversation could be recovered.
Notes
I am not attaching raw rollout history because it can contain private prompts, tool outputs, and encrypted model state. The practical workaround was:
- Back up the rollout file byte-for-byte.
- Keep parseable JSONL records.
- Drop top-level encrypted reasoning records.
- Drop nested encrypted compaction/reasoning entries.
- Drop malformed/NUL/partial JSON rows.
- Verify no structured
encrypted_contentkeys remain and that final user-visible messages are still present.
This seems like a good candidate for a built-in codex doctor or codex repair-history check as well.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗