Repository navigation
No thread works both in the panel and via CLI at the same time (writer-lock vs. panel-visibility conflict) #45406
Description
What version of the IDE extension are you using?
26.908.31748 (auto-updated today from 26.901.22334 -> 26.908.40401 -> 26.908.31748)
What subscription do you have?
Plus
Which IDE are you using?
VS Code 1.132.0
What platform is your computer?
Linux 7.0.0-31-generic x86_64
What issue are you seeing?
When a thread is open in the panel, it holds a live OS-level write lock (confirmed with lsof / flock -n), which correctly blocks codex exec resume <id> from the CLI with:
thread already has an active writer (code -32600)
This makes sense as protection against concurrent writers. But there's no supported way to hand off or release that lock intentionally - e.g. to let a CLI automation drive a thread the user was previously working on in the panel, without corrupting it. Is there a planned mechanism for this (explicit release/handoff), or is "one thread = one interface at a time, permanently" the intended model?
What steps can reproduce the bug?
- Open an existing Codex thread in the VS Code panel (Chats list) - leave it open.
- From a terminal, use the extension's own bundled CLI binary
(.../openai.chatgpt-/bin/linux-x86_64/codex) to run:
codex exec resume "any prompt" - Observe the command fails with:
thread already has an active writer (code -32600) - Confirm at the OS level this is a genuine active lock, not a stale one:
- ls -la ~/.codex/thread-writer-locks/.lock exists
- lsof shows the extension's app-server process holding
an open FD on it with the write-lock flag (e.g. "43uW") - flock -n -c 'echo got it' fails to acquire it
- There is no command/menu option in the panel to release, share, or hand
off that lock to let a CLI process drive the same thread.
What is the expected behavior?
Either:
(a) the panel exposes some explicit way to release/hand off a thread's
write lock so a CLI process (e.g. an automation or a second tool) can
take over driving it intentionally, without corrupting history, or
(b) if "one thread = one writer for its entire open lifetime" is the
intended permanent model, documentation/error messaging should say so
explicitly, so it's clear this isn't a bug or a stuck/stale lock -
right now the error message alone doesn't distinguish "temporarily
busy, retry" from "permanently locked until you close the panel."
Additional information
Extension auto-updated during this investigation: 26.901.22334 -> 26.908.40401 -> 26.908.31748, all within the same day. Behavior was consistent across all three versions - this does not appear to be a regression tied to a specific build.
codex-cli 0.154.0-alpha.6.2, VS Code 1.132.0, Linux 7.0.0-31-generic x86_64.
Activity
github-actions commentedon Sep 14, 2026
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
abruption commentedon Sep 15, 2026
Proposal: owner-cooperative release and handoff for live thread writers
I investigated this together with the related Remote Control case in #44449 and
several real lock holders on macOS. The important distinction is that these are
usually live kernel locks held by a legitimate Codex process, not stale lock-file
residue. Deleting
<thread-id>.lockcannot release such a lock and can make thestate harder to reason about.
Current
mainalready has most of the safe owner-side lifecycle machinery:WriterLockCoordinatoruses a real nonblocking OS lock and removes onlyunlocked stale files.
thread/unsubscriberemoves a connection's subscription.thread/closedafterthread_unload_delay_secs(60 seconds by default, zerofor immediate unloading).
What appears to be missing is an explicit, observable handoff contract between
products/processes. I suggest building that contract around cooperative release
by the process that owns the writer, rather than allowing another process to
delete files or kill the owner.
1. Owner-side release operation
Either add an optional immediate mode to
thread/unsubscribe, or introduce asmall
thread/releaseoperation. A possible request is:{ "threadId": "...", "mode": "ifIdle" }The response should be structured rather than inferred from an error string:
ifIdleshould release only when the owning app-server can prove that:requires the loaded runtime;
Only then should it remove the runtime and drop
WriterLockGuard. The existingthread/closednotification can be the acknowledgement that ownership wasactually released. A contender should retry
thread/resumeonly after thatacknowledgement.
2. Product lifecycle integration
thread.
or disconnected, and viewing history alone should not keep unrelated threads
resumed indefinitely.
actually observing or running, rather than every recently viewed thread.
This directly addresses #44449 without weakening single-writer protection.
3. Structured conflict diagnostics
When
thread/resumeencounters a live writer, its JSON-RPC error data couldinclude non-sensitive fields such as:
{ "threadId": "...", "reason": "liveWriter", "ownerKind": "cli | appServer | remoteControl | unknown", "retryable": true, "suggestedAction": "releaseInOwner" }PID, command line, TTY, and cwd are useful for an opt-in local diagnostic command,
but probably should not be exposed in normal protocol errors. Lock-file presence
alone must never be reported as proof of a live owner; the OS lock probe and
process metadata are separate evidence.
4. Suggested regression coverage
ifIdlerelease and keeps its writer lock.after shutdown.
every previously viewed thread.
thread/closed,then resumes successfully.
An incremental first step could be the owner-side
ifIdlerelease plus structuredconflict data; panel and Remote Control affordances could then use the same
protocol without changing the lock's safety model.
peixotorms commentedon Sep 22, 2026
This is an example of something unnecessary. It should just takeover and thats it.
HenryFone commentedon Oct 1, 2026
Windows data point that may be useful for the release/handoff discussion here (Desktop 26.924.22138, CLI 0.158.0-alpha.2.1):
%USERPROFILE%\.codex\thread-writer-locks\<thread-id>.lockfor every thread it has loaded, and keeps holding it long after the thread is idle in the UI. A second process gets the -32600 active-writer conflict, exactly as reported.archived_sessionsconsistent, reversible via unarchive).That is why I think the owner-side
ifIdlerelease plus structured conflict diagnostics you outlined is the right shape: a contender's lock probe cannot distinguish "live owner, idle thread" from "live owner, active turn", and today no supported request lets an owner drop the lock on demand.For anyone stuck on the archive path meanwhile, I put the rename + official CLI (
archive/unarchive/delete) flow in a small stdlib-only local tool: https://github.com/HenryFone/codex-archive-manager (Windows 11 + 26.924 tested; 127.0.0.1 only; never edits the SQLite DB itself). Untested on Linux/macOS, and it does not implement resume or handoff.abreza commentedon Oct 8, 2026
Please add a read-only “Follow CLI” mode to the VS Code extension, showing live progress, tool output, and diffs from a CLI session running in background or tmux. The CLI should remain the sole writer, and closing the extension should not interrupt its work.
mrehan37 commentedon Oct 12, 2026
Queue helps,
i used claude to give codex the prompt/instructions so the lock thing effect me and thats why i made this thread but the same day i got the solution that queue can help, even for nomal message when the chat is not doing anything you just use the queue function cuz without queue you cant directly add anything to the chat, so tell your ai or update the scripts of yours to QUEUE everything it wanna send to the codex, by this way you can quue multiple commands