openai / openai/codex

Codex Desktop: new chats fail to resume while rollout JSONL is briefly empty

Open
#38,613 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

app app-server bug
Dominant language
Rust
Stars
125k
Forks
19.5k
PR merge metrics
PR metrics pending

Description

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

26.810.41047 (build 6570)

What subscription do you have?

20x Max

What platform is your computer?

Darwin 25.4.0 arm64 arm

What issue are you seeing?

Every newly started chat can immediately show this error:

Failed to resume chat
failed to read thread: thread-store internal error: failed to read session metadata
<redacted>/rollout-<redacted>.jsonl: rollout at <redacted>/rollout-<redacted>.jsonl is empty

The rollout later becomes non-empty, so this does not appear to be permanent session corruption.

Local diagnostic timing shows:

  • thread/start succeeds.
  • turn/start follows.
  • The app calls thread/resume roughly 37 ms after thread/start.
  • The rollout path already exists, but is still zero bytes while the background writer gathers Git/session metadata.
  • The running-thread resume path tries to read persisted session metadata and treats the transient empty file as a fatal error.

This appears to be a startup race in the app-server running-thread resume path.

What steps can reproduce the bug?
  1. Open Codex Desktop on macOS.
  2. Start a new chat in an existing Git repository.
  3. Submit a prompt.
  4. Observe the red “Failed to resume chat” error immediately after startup.
  5. Inspect the referenced rollout path at the time of the error: the file exists at zero bytes, then becomes a valid non-empty JSONL shortly afterward.

The app-server behavior can be reproduced more directly:

  1. Start a thread and retain its live thread ID and rollout path.
  2. Start the first turn.
  3. Allow the rollout path to exist as a zero-byte file before the first metadata record is persisted.
  4. Call thread/resume for that running thread.
  5. Observe that resume fails while reading session metadata from the empty rollout.
What is the expected behavior?

A newly started chat should open without an error toast.

When the requested thread is still running in memory and its live rollout file exists but is temporarily empty, thread/resume should recover by persisting the current thread snapshot and retrying the metadata read (or otherwise wait/retry until metadata is available).

Threads that are genuinely unmaterialized and have no rollout file should keep the existing “not materialized yet” behavior.

Additional information

Related reports cover adjacent paths, but not this exact failure:

  • #25621 covers thread/read encountering an empty rollout after a different UI trigger.
  • #38451 covers a Worktree startup thread/resume race where no rollout is found.
  • This report covers thread/resume for a running new chat when the rollout exists but is still empty.

A focused patch and regression test are already prepared:

The patch only repairs a zero-byte rollout for a thread that is already running in memory. It preserves the current error behavior for threads with no materialized rollout.

Verification completed:

  • just fmt
  • just fix -p codex-app-server
  • just test -p codex-app-server thread_resume_repairs_empty_running_rollout
  • just test -p codex-app-server thread_resume_rejects_unmaterialized_thread
  • just test -p codex-app-server thread_resume_with_empty_path_uses_running_thread_id

If this approach aligns with the intended app-server behavior, I would be happy to submit the prepared change if invited.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in the codex-app-server thread/resume handling described by the issue, then run the named regression tests: thread_resume_repairs_empty_running_rollout, thread_resume_rejects_unmaterialized_thread, and thread_resume_with_empty_path_uses_running_thread_id. Done means a running thread with a temporarily empty rollout resumes without an error, while an unmaterialized thread keeps its existing behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.