TUI: Ctrl+C while editing a previous message appends thread_rolled_back and hides the message

Open 💬 3 comments Opened Jul 6, 2026 by yuminhhuang

Summary

In the interactive Codex CLI TUI, pressing Ctrl+C while editing a previous message appears to be handled as a thread rollback instead of a harmless edit cancellation. The selected previous message disappears from the TUI/resumed conversation, while the original message is still physically present in the session JSONL.

Version

Originally observed while using codex-cli 0.142.0.

After updating, local codex --version currently reports codex-cli 0.142.5; The display bugs still exist, but I have not yet confirmed the bug still reproduces from start on 0.142.5.

Reproduction Steps

  1. Start or resume an interactive Codex CLI TUI session.
  2. Press Esc to select a previous user message.
  3. Press Enter to edit that previous message.
  4. Press Ctrl+C to quit/cancel the edit.
  5. Observe the TUI transcript or resume/fork the session.

Actual Behavior

The selected previous message disappears from the TUI transcript / reconstructed conversation.

Expected Behavior

Canceling edit mode should discard only the temporary edit buffer. The original previous message should remain visible and the logical conversation should remain unchanged.

JSONL Investigation

The original message is still physically present in the saved session file under ~/.codex/sessions/.../*.jsonl, so the message content is not deleted from disk.

However, after each reproduction, the JSONL has an appended event like:

{"type":"event_msg","payload":{"type":"thread_rolled_back","num_turns":1}}

In my affected session, each thread_rolled_back event corresponded to one disappeared previous message. Removing those rollback events from a backed-up JSONL session file restored the missing messages when resuming the session.

Hypothesis

Ctrl+C from previous-message edit mode is taking the rollback path instead of the edit-cancel path. This likely affects the reconstructed logical thread, not just the current TUI display, because the rollback event is replayed from JSONL on resume/fork.

View original on GitHub ↗

3 Comments

constantins2001 · 1 month ago

I reproduced the same underlying failure in the macOS Codex Desktop surface embedded in ChatGPT, so this is not limited to the CLI TUI.

Environment:

  • ChatGPT/Codex Desktop: 26.707.41301 (build 5103)
  • bundled codex-cli: 0.144.0-alpha.4
  • macOS 27.0 arm64

Sequence:

  1. A long-running thread had a completed user turn and completed assistant response.
  2. I sent a follow-up message.
  3. I stopped/interrupted that turn.
  4. I used the mobile app to edit the message.
  5. The edited/follow-up content and the preceding completed turn disappeared from the UI.

The content was recoverable from the local rollout JSONL. Around the failure, the durable log contains:

{"timestamp":"2026-07-11T14:35:06.224Z","payload":{"type":"user_message","message":"<redacted follow-up>"}}
{"timestamp":"2026-07-11T14:35:20.862Z","payload":{"type":"turn_aborted","reason":"interrupted"}}
{"timestamp":"2026-07-11T14:35:38.574Z","payload":{"type":"thread_rolled_back","num_turns":1}}
{"timestamp":"2026-07-11T14:36:21.061Z","payload":{"type":"thread_rolled_back","num_turns":1}}

The earlier completed prompt and assistant final response remain physically present in the same JSONL, but Desktop reconstruction hides them. Codex thread search could still find the thread, and direct JSONL inspection recovered the missing messages. Forking the affected thread from the app API failed twice with a generic error, while creating a fresh recovery thread worked.

This looks like the Desktop edit-after-interrupt path emits rollback events with the same destructive replay semantics reported here. The two consecutive thread_rolled_back events may explain why more than only the edited turn disappeared.

Expected: stopping a turn and editing/resubmitting its message should replace only the intended turn. It must not hide the preceding completed turn, and duplicate rollback events should not be emitted.

constantins2001 · 1 month ago

Confirmed temporary recovery workaround for the Desktop reproduction I described above.

The affected messages were still present in the rollout JSONL. The only records making them disappear during reconstruction were the two erroneous thread_rolled_back events immediately following the interrupted/edited turn.

What worked for me:

  1. Locate the affected thread file under ~/.codex/sessions/YYYY/MM/DD/rollout-*.jsonl.
  2. Make a complete backup before changing anything.
  3. Inspect the events around the interrupted turn and identify the unexpected thread_rolled_back records.
  4. Create a repaired copy that removes only those specific rollback-event lines, then replace the original JSONL atomically.
  5. Switch away from the thread and reopen it so the UI reconstructs the history.

Example, using the exact timestamps from my affected file as selectors:

session="$HOME/.codex/sessions/YYYY/MM/DD/rollout-...jsonl"
cp "$session" /tmp/rollout-before-rollback-repair.jsonl

awk '!/2026-07-11T14:35:38.574Z/ && !/2026-07-11T14:36:21.061Z/' \
  "$session" > /tmp/rollout-repaired.jsonl

mv /tmp/rollout-repaired.jsonl "$session"

Do not copy those timestamps literally: first inspect your own JSONL and target only the erroneous rollback records associated with the disappearance. Removing legitimate rollback events can restore turns the user intentionally rewound.

I performed the replacement while Codex Desktop was still running and the affected thread was idle; it worked, and a subsequent thread read returned both the previously completed proposal turn and the later interrupted user message. Closing Codex before replacement is likely safer because an active writer could otherwise append to the old inode. Keep the backup until the recovered thread has been verified.

This is only a recovery workaround. The underlying bug remains the duplicate/destructive rollback emission and replay behavior.

constantins2001 · 1 month ago

It happened for me when editing a message on mobile twice