Skip to content

Forked Codex sessions copy user messages from after the selected fork point #21025

Open

Description

@toptechie156

Update

There's been no update on the app but I see the issue isn't happening anymore for me when I take a fork in the codex app.

Not sure exactly what changed. 🤔

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

26.429.30905 (2345)

What subscription do you have?

Pro

What platform is your computer?

Darwin 25.4.0 arm64 arm

What issue are you seeing?

When creating a fork from an earlier point in a Codex session, the new fork includes user messages that were sent after the selected fork point.

Those copied messages also get rewritten with the new fork creation timestamp, which makes them look like they were sent fresh in the fork.

This makes it hard to trust the forked session history and makes debugging session timelines confusing.

Example

Parent session:

019df362-aa9f-7011-903e-4a0878d49fa0

Fresh fork:

019df3d2-6edb-7322-b537-34d4f10cb129

The fork session file:

~/.codex/sessions/2026/05/04/rollout-2026-05-04T21-59-07-019df3d2-6edb-7322-b537-34d4f10cb129.jsonl

The fork metadata says:

{
  "id": "019df3d2-6edb-7322-b537-34d4f10cb129",
  "forked_from_id": "019df362-aa9f-7011-903e-4a0878d49fa0",
  "timestamp": "2026-05-04T16:29:07.679Z"
}

But the fork contains these parent user messages, all rewritten to around 2026-05-04T16:29:08Z:

Now I want to have a completely branch new implementation...
Okay then based on this...
do not swap...
Use @Computer...
scroll and see everything

In the parent, those same messages originally happened earlier:

2026-05-04T14:29:36Z  Now I want to have...
2026-05-04T14:44:27Z  Okay then based on this...
2026-05-04T14:45:27Z  do not swap...
2026-05-04T14:57:37Z  Use @Computer...
2026-05-04T14:58:51Z  scroll and see everything

Expected Behavior

When I fork from an earlier point in a session:

  1. The fork should include only messages/events up to the selected fork point.
  2. Messages after the selected fork point should not be copied.
  3. Copied historical messages should preserve their original timestamps, or clearly be marked as copied history.
  4. Synthetic entries like <turn_aborted> should not appear as normal role=user messages.

Actual Behavior

The fork includes user messages from after the selected fork point.

The copied messages are written into the new fork with the fork creation timestamp, so they look like new messages in the fork.

The fork also includes synthetic entries like:

<turn_aborted>...</turn_aborted>

as role=user.

Impact

This breaks trust in session history. It becomes unclear which messages were actually sent in the fork and which were copied from the parent. It also makes timeline debugging and auditing user messages much harder.

What steps can reproduce the bug?

  1. In a codex session in mac app, take a fork from a previous message point in history.
  2. Compare the messages in context for both the original session and forked session.
  3. Ideally the forked session should have messages only till the point where it was forked in the original session but currently it copies all the messages (including one's from after the fork point)

What is the expected behavior?

No response

Additional information

No response

Activity

  1. added
    appIssues related to the Codex desktop app
    on May 4, 2026
  2. added
    bugSomething isn't working
    sessionIssues involving session (thread) management, resuming, forking, naming, archiving
    on May 4, 2026
  3. github-actions commented on May 4, 2026

    @github-actions
    Contributor

    Potential duplicates detected. Please review them and close your issue if it is a duplicate.

    Powered by Codex Action

  4. toptechie156 commented on May 5, 2026

    @toptechie156
    Author

    There's been no update on the app but I see the issue isn't happening anymore for me when I take a fork in the codex app.

    Not sure exactly what changed. 🤔

  5. cesarbahena commented on Jul 29, 2026

    @cesarbahena

    I can confirm this issue is still reproducible on a newer Windows build.

    Environment

    • Codex Desktop: 26.721.11231.0
    • Platform: Windows
    • Bundled app-server runtime recorded in the rollout: 0.146.0-alpha.3.1
    • History mode: legacy

    Observed behavior

    I forked a conversation from an earlier message. The fork’s visible UI history ended at the selected point, but the child rollout contained later messages from the parent.

    Those later messages:

    • Were copied into the child’s .jsonl rollout.
    • Were rewritten with the child fork’s creation timestamp.
    • Were available to the model even though they were not visible in the fork UI.
    • Caused the assistant to reference work that only happened later in the parent conversation.

    This reproduced twice, approximately five minutes apart, with two separate child thread IDs.

    Local evidence

    Both child rollout files:

    • Have their own child session IDs.
    • Identify the same source using forked_from_id.
    • Contain parent turns created after the selected fork point.
    • Record the inherited turns at the child’s creation timestamp.

    The Desktop log confirms successful thread/fork calls for both children.

    I also inspected the packaged Desktop app.asar. The Desktop fork path sends a thread/fork request containing fields such as threadId, path, cwd, configuration, model, and developer instructions, but it does not appear to send lastTurnId.

    This is significant because the documented app-server contract says that lastTurnId is what limits copied history to the selected turn:

    https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md

    Without that boundary, the app-server copies history through the current tip of the source thread.

    Impact

    This is more than a confusing timestamp or UI-history problem. Later parent content becomes model-visible inside a fork that appears isolated at an earlier point.

    That means “Fork from here” cannot currently be relied upon as a conversation isolation boundary. Prompting the model to ignore leaked history is not an adequate workaround because the unwanted content has already been supplied to the model.

    Expected behavior

    When Desktop forks from a selected message, it should:

    1. Pass the selected completed turn as lastTurnId, or use the corresponding supported boundary mechanism.
    2. Persist only history through that boundary in the child rollout.
    3. Ensure the UI-visible history and model-visible history are identical with respect to the fork boundary.

    I can provide sanitized rollout metadata, timestamps, and Desktop log excerpts if maintainers need them. I am intentionally not posting transcript contents or complete local thread identifiers publicly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appIssues related to the Codex desktop appbugSomething isn't workingsessionIssues involving session (thread) management, resuming, forking, naming, archiving

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions