openai / openai/codex

Forked session is hidden from resume picker until its first new message

Open
#39,553 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI session TUI
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Codex version

codex-cli 0.148.0

Platform

Linux x86_64, terminal TUI

Problem

A newly created fork does not appear in the codex resume picker until the user sends a regular message in the fork.

The fork is already durable and directly resumable before that message. It has a rollout file, a row in state_5.sqlite, the expected cwd, source = cli, and archived = 0. Renaming the fork also succeeds and persists the name. Direct lookup works:

codex resume <fork-thread-id>

However, neither of these lists it:

codex resume
codex resume --all

Changing the picker sort order or cwd filter does not help. As soon as one regular user message is submitted in the fork, it appears in the picker.

Reproduction
  1. Open an existing interactive CLI session with conversation history.
  2. Run /fork, or start a fork with codex fork <thread-id>.
  3. Optionally run /rename in the new fork. Do not send a regular message.
  4. Note the new thread ID from /status.
  5. In another terminal, run codex resume --all.
  6. Observe that the fork is missing from the picker.
  7. Run codex resume <fork-thread-id> and observe that the fork opens successfully.
  8. Submit one regular user message in the fork.
  9. Run codex resume --all again. The fork is now listed.

This reproduced twice with fresh forks. The second reproduction was done after all older Codex processes had exited, so mixed CLI versions were ruled out.

Local evidence

Before the first message, the fork had already been written to the normal persistence surfaces:

threads.id             = <fork-thread-id>
threads.source         = cli
threads.thread_source  = user
threads.archived       = 0
threads.history_mode   = paginated
threads.name           = <persisted rename>
threads.rollout_path   = <existing rollout file>
threads.preview        = ''
threads.has_user_event = 0

The distinguishing field is the empty preview. In codex-rs/state/src/runtime/threads.rs, ordinary thread listings add:

AND threads.preview <> ''

The resume picker uses this listing path. A direct UUID resume uses thread/read, so it bypasses that filter. Sending the first regular message fills the preview and makes the fork visible.

Expected behavior

A persisted fork that can be resumed by UUID should appear in the resume picker before it receives a new message. This is especially important after an explicit rename: the user has created and named a branch of an existing conversation, not an accidental empty session.

The empty-preview filter is useful for brand-new sessions that were opened and abandoned without input, but a fork already contains inherited conversation history. It should not be treated as an empty disposable thread.

Possible fix

The listing policy could include persisted forks even when their preview is empty, rather than removing the empty-preview filter globally. Another option is to give a fork a display preview derived from its inherited history, although that may blur the distinction between inherited content and the first message created in the fork.

This is related to #21619 because both failures end at the empty-preview listing filter, but the trigger is different. #21619 concerns an existing rollout whose first user event is beyond a bounded scan. This report is a deterministic fresh-fork case: persistence and rename succeed, but the child has no child-owned user event yet.

We would be happy to prepare a PR with a focused regression test and fix if maintainers agree on the desired listing semantics.

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 codex-rs/state/src/runtime/threads.rs and trace the ordinary thread-listing query, especially its empty-preview filter. Reproduce with a fresh fork, then compare codex resume and codex resume --all before and after the first message. Done means the intended persisted-fork listing behavior is covered by a focused regression test without breaking handling of abandoned empty sessions.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust, sqlite
Domain
cli, database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.