A thread admits one writer at a time
The app-server tracks who is writing and turns away anyone else. This is a lock rather than a fault: the alternative is two turns appending to one history, which ruins the thing both of them were trying to use.
Codex CLI fix: Codex refuses a thread that already has a writer
One conversation, one writer. Codex refuses the second rather than interleaving two streams into a history that would then belong to neither of them.
already has an active writer
Printed by Codex CLI.
Diagnosis
The app-server tracks who is writing and turns away anyone else. This is a lock rather than a fault: the alternative is two turns appending to one history, which ruins the thing both of them were trying to use.
A terminal in another window, an editor extension, or a session left open on a second screen all hold it. The lock belongs to a process, not to a person.
The lock releases when the process ends. A killed process is normally noticed at once, and the moment in between is exactly when the refusal looks wrong.
Check
| Run this | What a good answer looks like |
|---|---|
codex agents | Lists the sessions on the shared local app-server daemon, which is where a forgotten writer turns up. |
ps -eo pid,etime,cmd | grep "[c]odex" | Every Codex process with its age. More of them than you expected is the answer, and the oldest is usually the holder. |
Every command here has been run on a real machine. Termdeck answers the same questions for every machine you have connected, without opening a terminal on any of them.
Fix
The lock lifts when the process holding it ends its turn or exits. Nothing else releases it.
Codex has a fork subcommand for exactly this. It continues from the same history in a separate thread, so neither writer has to yield.
A new session cannot conflict, and it costs nothing when the task matters more than the transcript.
Not this
The lock is held by a running process rather than by the file. Deleting it loses the history and changes nothing about the refusal.
FAQ
Both would append to one history. Refusing the second is what keeps the transcript coherent enough to resume.
A fork continues from the same history and diverges from that point rather than duplicating a file.
The idea is the same, one writer per conversation. Which process enforces it is what differs.
Claude Code, Codex and Grok in one browser console