Repository navigation
Remote Control: threads viewed in the iOS app stay locked in the daemon, desktop fails with "already has an active writer" #44449
Description
What version of the Codex App are you using (From "About Codex" dialog)?
26.901.20858 (macOS), embedded app-server 0.153.x; Remote Control daemon codex app-server --remote-control 0.153.1; terminal CLI 0.153.4.
What subscription do you have?
ChatGPT Pro
What platform is your computer?
macOS 26.2 (25C56), Apple Silicon
What issue are you seeing?
Threads that I last opened in the ChatGPT iOS app (Codex tab, Remote Control) become unopenable in the Codex desktop app on the same Mac. Clicking them in the sidebar fails with:
thread 01a0831e-aec8-77c2-9295-7beeddf97692 already has an active writer
The desktop shows the thread as open elsewhere. Nothing is visibly open on the phone; the app is in the background. The model picker on those threads is also disabled, so they cannot be moved from GPT-5.6 Sol to GPT-6 Astra until the lock clears.
The cause is visible in logs_2.sqlite. When the iOS client (codex_chatgpt_ios_remote 1.2026.237) reconnects, the backend sends __slingshot_backend_notification_thread_resume__ for every thread the phone had touched, and the Remote Control daemon resumes all of them. Each resumed thread takes a writer lock in ~/.codex/thread-writer-locks/<thread>.lock. The desktop's own app-server then cannot resume them until the daemon tears the threads down, which happened about 50 minutes later.
Timeline from one occurrence (UTC, 2026-09-09):
20:35:23-20:35:26 daemon (pid 40273): 8 thread/resume requests, request_id
__slingshot_backend_notification_thread_resume__:<id>, connection 556
threads incl. 01a0802c…, 019fce14…, 019feb04…, 01a0831e…
21:07:50 desktop app-server: thread/resume 01a0831e… -> -32600 already has an active writer
21:08:23-21:13:01 same for 019fce14… (12 attempts)
21:23:55-21:26:23 same for 01a0802c… (8 attempts)
21:28:24 daemon: "clearing thread listener during thread-state teardown" for all three,
op: Shutdown, "Agent loop exited"; desktop can open them again
lsof on ~/.codex/thread-writer-locks/ during the window showed only the desktop's app-server holding locks for threads it had itself opened. The failing threads' locks were held by the daemon process. No turn was running in those threads on the phone.
What steps can reproduce the bug?
- Enable Remote Control in Codex desktop on a Mac.
- In the ChatGPT iOS app, open the Codex tab and view three or four threads hosted on that Mac. Background the app.
- Later, bring the iOS app back to the foreground (or let it reconnect).
- In Codex desktop on the Mac, click any of those threads in the sidebar.
Observed: already has an active writer, thread cannot be resumed or have its model changed. Waiting until the daemon tears the threads down (tens of minutes) clears it. Closing the Codex tab on the phone also clears it.
What is the expected behavior?
Viewing a thread on the phone should not lock it against the desktop on the machine that hosts it, at least while no turn is running. Either the daemon should release idle threads when the phone is backgrounded, or the desktop should be able to take the thread over from the daemon (or open it read-only, as #43253 did for the TUI) instead of failing.
Additional information
Related but different: #43374 and #44063 are stale locks left by an exited process. Here the lock holder is alive and legitimate; the problem is that a backgrounded phone client keeps every recently viewed thread loaded in the daemon. #43253 added a read-only fallback for the TUI only.
Activity
abruption commentedon Sep 15, 2026
I posted a concrete owner-cooperative release/handoff proposal in #45406: #45406 (comment). For this Remote Control case specifically, the proposed lifecycle rule is to unsubscribe on view close/background/disconnect, avoid resuming every recently viewed thread on reconnect, and release only after the owner proves the thread idle and flushes/shuts down its recorder. This preserves the native single-writer guarantee while preventing an idle remote viewer from blocking Desktop for tens of minutes.
guayom commentedon Sep 22, 2026
Independent reproduction on the current desktop build: this still affects the iPad Remote flow.
Environment
26.915.31945(build9922)15.6.1(24G90)Observed behavior
thread/resumefromsource=thread_hydrationfailing with code-32600:thread [redacted] already has an active writer.notLoaded; its transcript is still readable and its recent turns are completed, so no turn appears to be running.Recovery attempted
The failure persists after all of the above.
Impact
A specific completed thread cannot be loaded from iPad Remote or resumed normally despite no visible active turn. This appears consistent with the Remote Control daemon retaining writer ownership; restarting the desktop app alone does not release it.
I can provide the full thread ID privately if maintainers need it.
EasterFan commentedon Sep 23, 2026
I can reproduce the same issue on Android.
Environment
Steps to reproduce
The task is already complete, but the session cannot be opened on the phone. The desktop side reports an active-writer conflict, even though no turn is running.
This appears to be related to the remote client resuming a completed thread as an active writer instead of opening it in read-only mode or releasing ownership after the task finishes.
Expected behavior
The completed conversation should load normally on Android and allow the user to continue it, or show a clear handoff or reconnection message instead of loading indefinitely.
shlomi98 commentedon Oct 4, 2026
I’m seeing the same issue with the Codex VS Code extension on Windows.
My workflow:
"Another Codex session is using this task.
Finish and close that session, then try again."
This has been happening for several months across multiple Codex VS Code extension updates, so it does not appear to be a one-version regression.
Claude Code Remote Control works correctly with the same general workflow: I can leave the desktop session running and continue controlling it remotely.
For Codex, having to finish/close the desktop VS Code session before connecting from iOS defeats the purpose of Remote Control.
Environment:
Aragorn2046 commentedon Oct 5, 2026
Independent confirmation from another ChatGPT Pro / Codex Remote Control user.
This is a significant regression in the Remote Control workflow for me. I previously used Remote Control specifically so that I could leave multiple Codex sessions running on my machines and freely inspect/steer those sessions remotely from the mobile app.
Recently I increasingly get the equivalent of "this task is active elsewhere / close it there and try again here", forcing me to close or hand off sessions before I can control them remotely.
That breaks the core Remote Control use case. The machine should be the execution plane and mobile/desktop clients should be interchangeable control surfaces. A session being open on its host should not prevent Remote Control from attaching to or steering it.
The important behavioral regression from my perspective is:
Previously:
host session remains running → open mobile Remote Control → inspect/steer session → continue normally
Now:
host session remains running → open mobile Remote Control → session considered owned/active elsewhere → close/handoff required → then regain control
Even if single-writer semantics are required internally, they should be invisible to the user. Remote needs either safe ownership transfer, an observer mode that can become writer when steering, or shared control semantics.
Please restore the previous seamless Remote Control behavior. Requiring users to close sessions on the machine they are remotely controlling defeats much of the purpose of Remote Control.
hqy117 commentedon Oct 7, 2026
I’m seeing the same issue.
Environment:
In my case, threads that I opened from Remote Control on iOS remained locked even after I disconnected Remote Control from the phone.
After that, trying to open those same sessions from the VS Code extension failed with an "already has an active writer" error. Other sessions that had not been opened from iOS were still accessible normally.
Reloading the VS Code window did not help.
I checked the writer locks with:
and found that multiple threads were still being held by the same Codex Remote Control app-server process:
The process had PPID 1 and continued running even after Remote Control had been disconnected on iOS.
After killing that daemon process, all affected sessions immediately became accessible again from the VS Code extension.
So this looks consistent with the Remote Control daemon retaining writer ownership for threads previously viewed on iOS, instead of releasing them when the mobile Remote Control session is disconnected.
It would be very helpful to have either:
hqy117 commentedon Oct 7, 2026
Additional observation / workaround:
I tested the issue in both directions, and the writer lock appears to persist on whichever client opened the thread.
Current workaround that consistently works for me:
iOS Remote Control opened the thread -> VS Code cannot open it:
codex remote-control stopVS Code opened the thread -> iOS Remote Control cannot open it:
run
Developer: Reload Windowin VS CodeSimply switching to another chat/session is not enough to release the thread on either side.
So at least in my setup, this looks like a bidirectional thread ownership / writer-release issue rather than something specific to the iOS Remote Control daemon.
A per-thread explicit "Release" / "Hand off" action would probably make this much easier to use without restarting either side.
hosannasub commentedon Oct 10, 2026
Another Linux/iOS Remote reproduction, this time on Codex 0.160.0, with one additional observation that may help distinguish idle retention from a live ownership-tree problem.
The affected app-server retained the parent thread plus several child/subagent writer locks. I sampled the corresponding rollout files over 15 seconds and found:
session_meta on the active child confirmed it was a depth-1 subagent of the affected top-level thread via parent_thread_id, forked_from_id, and thread_source: "subagent".
So there appear to be at least two states in this bug family:
In the second state, killing only lock files would be unsafe because the owning process is still legitimately writing. My recovery was to identify the exact app-server owning the execution tree, verify which of its threads were actually changing, terminate that app-server, verify the parent rollout froze cleanly, then fork from the latest persisted parent.
SIGTERM did not terminate the old app-server in this occurrence; SIGKILL was required.
After termination, the writer lock released immediately and the persisted JSONL remained valid.
This makes me think the fix may need to address owner lifecycle and handoff at the app-server/execution-tree level, not only release idle threads on mobile background/disconnect.
Environment:
codex-cli / app-server 0.160.0
Linux remote host with ChatGPT iOS Remote / SSH workflow.
jaeilnet commentedon Oct 13, 2026
I encountered a similar issue on 2026-10-13. Adding diagnostic evidence from this occurrence.
Environment
26.1007.30912(running from ChatGPT.app)0.162.1Observed behavior
Two conversations that I had been using from mobile later became inaccessible, with a message indicating that they were in use in another session. The exact original UI error text was not captured, so this is a paraphrase.
Affected thread IDs:
01a1337c-c900-7082-9998-604f058500d101a133a3-61be-78c1-a258-b2fcc1644329Both threads appeared as
notLoadedthrough the desktop app tools. Their latest recorded turns were completed, and their histories could still be read throughthread/read.However,
lsofshowed that a separate live managed daemon held both thread writer lock files and both rollout files:The latest recorded task completion timestamps were:
Recovery attempts and results
task_complete.codex app-server daemon restart. The command succeeded, replacing PID 99487 with PID 93528.lsof: the new daemon had acquired both affected thread lock files again. Restarting alone therefore did not clear the observed lock ownership.codex app-server daemon stop.lsofthat neither affected lock file had an open owner afterward. No conversation histories or lock files were deleted.Successful reopening from mobile has not yet been confirmed. These observations establish live daemon ownership and reacquisition after restart; they do not establish which reconnect/subscription event caused it. We did not capture the backend resume notifications described in the original report.
It would help if idle thread ownership could be released or handed off automatically, and if the inaccessible-thread UI identified the owning backend and provided a safe recovery action without requiring users to stop the entire daemon.