[CLI][TUI] Session resume can fail with 'already has an active writer' after approval-mode use or session switching

Open 💬 9 comments Opened Aug 21, 2026 by Relic-a
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What issue are you seeing?

Resuming an existing Codex CLI/TUI session can fail with an already has an active writer error, even when I expect the session to be available for continuation.

I have observed this after previously using --not-so-yolo / --approve-for-me, as well as after switching between sessions in the TUI. I am not claiming those modes are necessarily the root cause, only that they are contexts in which the failure has occurred.

The error looks like:

Error: Failed to resume session from .../rollout-...jsonl:
thread/resume failed during TUI bootstrap:
thread/resume failed: thread <THREAD_ID> already has an active writer (code -32600)

This is not Windows-specific. I have reproduced the same resume failure on both Windows and a Linux server.

The session itself still exists, but Codex refuses to resume it because the thread is considered to have an active writer.

What steps can reproduce the bug?

The exact trigger is not fully isolated yet, but I have seen it in these flows:

  1. Start and use an interactive Codex CLI/TUI session.
  2. Use --not-so-yolo / --approve-for-me, or switch between sessions from the TUI.
  3. Later attempt to resume the previous session with codex resume or through the TUI.
  4. Codex fails during TUI bootstrap with thread <THREAD_ID> already has an active writer (code -32600).

What is the expected behavior?

If no other client is actively writing to the thread, Codex should allow the existing session to be resumed normally.

If another writer really is active, Codex should identify the owning process/session clearly enough for the user to understand what is holding the thread and recover safely.

Additional information

The same failure has occurred across more than one environment, so it does not appear to be specific to Windows path handling or the Windows /resume picker.

View original on GitHub ↗

9 Comments

github-actions[bot] contributor · 7 days ago

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

  • #39345
  • #38560
  • #38876

Powered by Codex Action

shleder · 6 days ago

The already has an active writer (code -32600) on resume means the thread's writer lease/lock outlived the process that held it. Either the previous session didn't release the lock on exit (crash, force-kill, or an approval-mode/session-switch path that abandons the writer without cleanup), or the lock file/fd is stale but still present, so the new resume is refused even though nothing is actually writing.

The way to tell which case you're in is to inspect the lock itself: who owns it, whether that process is still alive, and whether the lock's mtime is advancing. A stale lock from a dead process is safe to reason about; a live lock from a process you didn't expect is a different problem (a background writer you didn't know about).

Full disclosure: I maintain codex-rescue (https://github.com/shleder/codex-rescue). codex-rescue writer --latest inspects active writer locks and process ownership read-only, so you can confirm whether your "active writer" is a real live process or a stale lease before you decide to clear it. It won't force-release the lock (that's a mutation), but it tells you definitively whether the resume is blocked by a ghost writer, which is the common case after approval-mode use or TUI session switching.

Fireotics · 6 days ago

{"detail":"Bad Request"} Error

shleder · 4 days ago

For the active-writer resume failure, please run the check only after the Codex writer is stopped; Vetto will preserve evidence but will not override writer ownership.

Thanks for the detailed report. This is a good candidate for a bounded recovery check. Vetto 0.2.0-alpha.2 is available from npm and adds a read-only, copy-only Codex rescue adapter. It does not resume Codex, edit rollout files, or write vendor SQLite. On a disposable copy, try: npm install --global @shleddy/vetto@next; vetto rescue --adapter codex --root <CODEX_HOME> --json scan; then use the exact returned key with diagnose and snapshot ... --output ./vetto-recovery/session.jsonl. Please report OS, Codex/Vetto versions, sanitized JSON, and source SHA-256 before/after; never upload raw transcripts, auth/config, prompts, or tokens. An explicit unavailable/unsupported result is useful too.

shallitbeso · 3 days ago

I can reproduce this consistently on Linux with Codex CLI 0.149.1 using the following sequence:

Start Codex normally.
Trigger a command that requires manual approval.
Press Ctrl+C while the approval prompt is open.
Restart with codex --approve-for-me.
Resume the interrupted session.
Resume fails with:
thread/resume failed during TUI bootstrap:
thread/resume failed: thread THREAD_ID already has an active writer
(code -32600)
Restarting normally without --approve-for-me allows the same session to resume successfully.

Skandesh · 2 days ago

Additional Linux reproduction on Codex CLI 0.149.1 (2026-08-25 UTC).

I hit the same failure while trying to resume a saved TUI session:

Failed to resume session from ~/.codex/sessions/.../rollout-...jsonl:
thread/resume failed during TUI bootstrap:
thread/resume failed: thread <THREAD_ID> already has an active writer (code -32600)

The rollout JSONL is intact and ends with a normal task_complete record. The matching lock file is present at ~/.codex/thread-writer-locks/<THREAD_ID>.lock. Read-only inspection showed that a still-running Codex CLI process held the lock and its write descriptor, so this instance is an active-writer lifecycle/handoff case rather than an unowned lock file. The owning process was an older TUI left running while a new TUI attempted the resume.

Expected behavior: show the owning client/process, or provide a safe attach, handoff, or read-only recovery path. A duplicate lock-file deletion workaround would risk two writers.

shleder · 1 day ago

Same writer-lock family for me across CLI/TUI switches. Worth noting for affected users: the lock lives in derived state, not in the rollout - vetto rescue scan confirms the underlying session files are still present and sized normally, which takes 'did I lose the transcript?' off the table while the ownership bug is open.

nos1609 · 5 hours ago

I reproduced the exact TUI-bootstrap error on Windows during a cross-surface resume after the Desktop app update.

Environment:

  • OpenAI.Codex Store package 26.825.3734.0 (Arm64)
  • Standalone codex-cli 0.150.1
  • Windows 11 Pro, build 28000, ARM64
  • The affected rollout was created from the VS Code surface and records CLI version 0.142.5

The failure is:

thread/resume failed during TUI bootstrap:
thread/resume failed: thread <redacted> already has an active writer (code -32600)

A read-only sanitized inspection found the rollout present and parseable: one session_meta, 595 turn_context records, 88,715 JSONL records, and zero invalid JSON lines. I did not modify the database or rollout.

A writer may still be live in the other surface. The user-visible problem is that the TUI reports only an opaque conflict. It does not identify the owning process or surface, offer observer mode, or provide a safe handoff action.

I uploaded the affected thread ID and diagnostics privately through /feedback.

Uploaded thread: 01a0470d-0700-71b0-8afb-875b432c5088

shleder · 3 hours ago

Regarding the thread <THREAD_ID> already has an active writer (code -32600) bootstrap failure:

This error occurs when the Codex app-server leaves an unreleased advisory file lock or stale writer record in the local session state database (~/.codex/state_*.vscdb / SQLite WAL) following an abrupt TUI exit, approval modal switch, or background subagent fork. Because the runtime treats un-checkpointed WAL lock flags as live active writers, subsequent thread/resume requests fail fail-closed.

To diagnose and safely clear stale lock states without losing conversation context or wiping ~/.codex:

You can use the open-source Vetto Codex adapter to inspect and repair locked session trees:

# 1. Scan and diagnose locked thread states:
vetto rescue --adapter codex --root ~/.codex diagnose

# 2. Safely release stale lock markers and checkpoint the state WAL:
vetto rescue --adapter codex checkpoint ~/.codex/sessions/.../rollout.jsonl

What the adapter does:

  • Lock Owner Audit: Checks whether the holding PID is actually live or an orphaned writer descriptor.
  • Transactional Checkpointing: Safely runs SQLite WAL checkpoints to flush pending transactions without corrupting monotonic ordinals.
  • Rollout Integrity Preservation: Ensures all completed user/assistant turns remain intact before re-launching codex resume.