TUI /resume intermittently forks the selected session into a new thread ID

Open
#34,972 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
45/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
rust, sqlite
Domain
cli, databases

Research direction

Start at the TUI /resume entry point and compare the thread/resume and thread/fork paths. Reproduce with repeated resume and picker cycles, then inspect state_5.sqlite, rollout files, and session_meta for forked_from_id; done means /resume preserves the selected thread ID without adding a session, while explicit fork still creates one.

Written by the indexing model from the issue text.

Description

bug CLI session TUI
What version of Codex CLI is running?

codex-cli 0.145.0

One affected session was originally created with 0.143.0, but the issue also reproduced when both the parent and child were created with 0.145.0.

What subscription do you have?

ChatGPT subscription; the exact tier is not exposed by the local diagnostics used for this report.

Which model were you using?

gpt-5.6-sol

What platform is your computer?

Ubuntu 20.04, Linux x86_64.

What terminal emulator and version are you using?

GNOME Terminal; exact version unknown.

What issue are you seeing?

The TUI /resume command intermittently creates a new thread ID instead of resuming the selected thread in place.

This does not happen on every resume. I observed it twice on 2026-07-23, but I do not yet have a deterministic trigger.

When the issue occurs:

  1. I type /resume in the Codex TUI.
  2. I select an existing CLI session.
  3. The selected conversation opens with its previous history.
  4. Codex also creates a new rollout file with a new session ID.
  5. The new rollout's session_meta contains forked_from_id pointing to the selected session.
  6. Both the original and the new session remain visible in the /resume picker with nearly identical content.

This makes /resume behave like /fork even though I did not request a fork.

Persisted-state evidence

I inspected state_5.sqlite and the affected rollout files using read-only queries. No transcript contents, full session IDs, account identifiers, or project paths are included in this report.

Three affected entries form this chain:

Role Created CLI version Source forked_from_id
Original (019f4283…) 2026-07-08 0.143.0 cli, thread_source=user absent
Unexpected child 1 (019f8973…) 2026-07-22 0.145.0 cli, thread_source=user original ID
Unexpected child 2 (019f8e63…) 2026-07-23 0.145.0 cli, thread_source=user unexpected child 1 ID

The three session IDs are different, but their persisted first_user_message values are exactly equal, and each has a valid, distinct rollout file.

The relevant session_meta shape is:

{
  "originator": "codex-tui",
  "source": "cli",
  "thread_source": "user",
  "cli_version": "0.145.0",
  "forked_from_id": "<previous session id>"
}

codex doctor --json reports:

state DB integrity: ok
rollout DB duplicate DB paths: 0
rollout DB duplicate rollout thread ids: 0
rollout DB scan errors: 0

The doctor report also contains two unrelated stale rows, but neither stale row belongs to the affected chain. Every affected session has a valid rollout file.

Internal Guardian/subagent threads also exist in the inventory, but these three affected entries are ordinary cli/user threads, not Guardian or subagent sessions.

What steps can reproduce the bug?

The issue is intermittent.

Observed workflow:

  1. Start Codex TUI inside a project.
  2. Work in a normal CLI session and exit or switch away from it.
  3. Later, type /resume.
  4. Select that existing session.
  5. Continue using the restored conversation.
  6. Open /resume again and inspect the session list.
  7. Sometimes a second session with the same history is present.
  8. Inspecting its rollout shows a new ID and forked_from_id pointing to the selected session.

Repeating this can produce a chain in which each unexpected child points to the previous child.

Not every /resume produces a new ID, so there may be a race, loaded/unloaded thread-state distinction, app-server state difference, or another conditional path deciding between thread/resume and thread/fork. This is a hypothesis, not a confirmed root cause.

What is the expected behavior?

/resume should continue the selected thread using its existing thread ID.

Only an explicit /fork or codex fork operation should create a new thread ID with forked_from_id.

At minimum:

  • /resume should consistently use the resume path;
  • it should not create a new top-level session unexpectedly;
  • the resume picker should not accumulate multiple copies of the same logical conversation;
  • if persistence requires an internal continuation record, the UI should represent the chain as one logical session rather than multiple independent entries.
Additional information

Possibly related issues:

  • #29531 — resume creates new date-based rollout files containing duplicated historical context
  • #22593 — forked sessions store forked_from_id and copy parent history
  • #19267 — intermittent duplicate same-title thread records with distinct IDs and rollout files

None appears to cover the exact combination observed here: Codex CLI/TUI, /resume, intermittent behavior, and an unexpected forked_from_id chain.

I can provide a redacted codex doctor --json report and sanitized session_meta records if maintainers need them. I will not post transcript contents publicly.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

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.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.