Desktop: chat disappears after restart when one host is connected through both SSH and Remote Control
What version of the Codex App are you using (From “About Codex” dialog)?
26.810.52044 (build 6662)
The bundled local app-server/CLI was 0.148.0-alpha.9 when I collected the diagnostics below.
What subscription do you have?
Pro
What platform is your computer?
Local Mac:
Darwin 25.5.0 arm64 arm
Remote machine:
Ubuntu 24.04
Linux 7.0.0-28-generic x86_64
The SSH app-server on the remote machine reported 0.144.1 during the incident. It reported 0.147.0 after Codex Desktop restarted and updated the managed copy.
What issue are you seeing?
I use Codex Desktop on my Mac as the UI for a project stored on a Linux machine. I had added that Linux machine to Codex in two ways:
- as an SSH project;
- through Remote Control under
Control other devices.
Both entries referred to the same physical machine and the same remote CODEX_HOME.
I created a chat while working in the SSH project. The next day I upgraded/restarted Codex on the Linux machine. When I reopened Codex Desktop on the Mac, the SSH project was still in the sidebar, but the chat was gone.
The chat had not actually been deleted. Its rollout file was still on the Linux machine. The file was about 1.15 MB, contained 342 valid JSONL records, and had no JSON parse errors. I could also read the complete chat directly from the remote app-server with thread/read and thread/turns/list.
While investigating, I found the same thread ID twice in Codex Desktop's local thread catalog:
host_id thread_id cwd
remote-ssh-codex-managed:<ssh-alias> <same-thread-id> /home/<user>/Repo/<project>
remote-control:<redacted-environment-id> <same-thread-id> /home/<user>/Repo/<project>
The two rows had the same title, timestamps, working directory, and source. The two copies also showed no project association (projectId: null) when listed through the Desktop task API.
The Desktop log shows both connections starting during the same launch:
Starting app-server connection hostId=remote-ssh-codex-managed:<ssh-alias> transport=websocket
Starting app-server connection hostId=remote-control:<redacted-environment-id> transport=websocket
It also contains this error while the SSH connection was starting:
Failed to load config requirements errorMessage="No AppServerRequestClient registered for hostId: remote-ssh-codex-managed:<ssh-alias>"
After I removed the duplicate Remote Control catalog data and restarted the app, the chat title came back. At first, opening it still showed a blank page even though the app-server could return the full chat. The content appeared only after the thread was explicitly opened/read using the SSH host identity.
What steps can reproduce the bug?
These are the steps that led to the problem on my machines. I have not repeated them with a clean profile because I do not want to risk my existing remote chat history.
- Add a Linux machine to Codex Desktop through
Connections > Control other devices. - Add the same machine as an SSH project.
- Open a project through the SSH entry and create a chat.
- Confirm that the rollout is stored under
~/.codex/sessions/on the Linux machine. - Leave both connection methods configured for the same machine.
- Upgrade or restart Codex on the Linux machine, then quit and reopen Codex Desktop on the Mac.
- Open the saved SSH project.
In my case, the existing chat was no longer shown. During recovery, the title later appeared with an empty conversation body even though direct app-server reads still returned the messages.
I have redacted the affected thread ID from this public report, but I can provide it privately if it would help with diagnosis.
What is the expected behavior?
Restarting or upgrading either side should not make a persisted remote chat disappear or open as an empty conversation.
If SSH and Remote Control can be used with the same machine and CODEX_HOME, Codex Desktop should keep the host and project association when it lists and opens a thread. If that setup is not supported, the app should warn the user instead of adding the same thread under two host identities.
Additional information
My best guess is that the upgrade/restart exposed an existing identity conflict rather than causing data loss. The Desktop catalog uses (host_id, thread_id) as its key, so the same thread ID can exist once under the SSH host and once under the Remote Control host. Some later lookup or UI path appears to expect one result or to lose track of which host was selected.
I also found an old standalone app-server process on the Linux machine. It may have made the restart behavior worse, but I do not think it explains why the Desktop catalog had the same thread under two host identities.
The workaround I used was:
- Back up the local and remote Codex databases and the affected rollout.
- Disable Remote Control auto-connect for the Linux machine.
- Stop the Linux Desktop/Remote Control process and the stale standalone app-server.
- Remove the Remote Control copy of the thread catalog/sync data while keeping the SSH copy.
- Restart Codex Desktop and reconnect through SSH.
- Open the thread using the SSH host identity.
After this, the catalog contained only the SSH mapping for the thread and the complete conversation loaded again.
Related issues:
- #33750 - Allow SSH and Remote Control clients to share the same app-server
- #22438 - Codex Desktop remote SSH connection does not show persisted remote sessions after app restart
- #35733 - Desktop auto-connects discovered SSH hosts at startup and blocks local chat loading when a host is unavailable
This looks related to all three, but I am opening a separate report because I could confirm that one persisted thread was indexed under both the SSH and Remote Control host identities.
I can provide sanitized Desktop log excerpts, the relevant catalog rows, and the app-server read results. I will not attach the full rollout, state databases, credentials, SSH configuration, or unredacted host identifiers to a public issue.
5 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
That double-indexed
thread_idunder bothremote-ssh-codex-managed:<ssh-alias>andremote-control:<environment-id>is the smoking gun...... the Desktop catalog is keyed on(host_id, thread_id)and you've got one thread, two host identities, both withprojectId: null, so neither side owns it. Quickest unblock: pick ONE host identity for that thread, prune the duplicate entry from the local Desktop catalog, and force a re-rollout of the persisted thread under the surviving host.rm -rfthe rollouts dir on the losing side is what fixed it for me before, but you already found that, so I'd check whether your recovery path is actually flipping the catalog and not just re-syncing the rollout file.I it is interesting, some of the project discussions moving back
randomly to the appropriate projects. Maybe AI trying to figure out where
those conversations belongs :)
L:
On Mon, Aug 17, 2026 at 10:19 PM Ringo @.***> wrote:
A Windows reproduction confirms the same identity collision, this time between a local task and a Linux Remote SSH task rather than two remote connection methods.
Environment:
Observed state before recovery:
thread_idunder two host identities.host_id=localand a Windows workspace root.read_threadcalls returned different histories for the two objects.list_threadscollapsed the records bythread_id. A pinned stale remote record hid the newer local record from both the sidebar and pinned list.navigate_to_codex_pageaccepts onlythreadId, nothostId, and opened the stale remote object.The current
local_thread_catalogschema explicitly uses the composite primary key:Therefore duplicate IDs across hosts are valid catalog entries, but downstream list and navigation paths do not consistently preserve the host component.
A non-destructive recovery confirmed the boundary:
threadIdand Remote SSHhostId.list_threads.The archived-task listing still exposes the stale remote object with the same ID, while the active listing exposes the local object. No transcript data was lost.
Expected behavior:
(host_id, thread_id)as the task identity throughout catalog hydration, pinning, deduplication, selection, and navigation.hostIdto direct navigation.One diagnostic initially suggested a separate state-index issue because an older
state_5.sqlitefile did not contain the ID. I excluded that claim here: the file had not been updated for months, while the active Desktop catalog database was current. This report only relies on live host-qualified task APIs and the active catalog schema.No task IDs, prompts, project names, usernames, hostnames, addresses, or private paths are included.
Follow-up to the Windows reproduction above: archiving the stale Remote SSH object repaired host resolution and direct navigation, but it did not fully restore sidebar visibility.
Current read-only state:
list_threadsreturns the surviving local task underpinnedThreads;activeand haspinnedIndex: 1;The actual Desktop sidebar still omits the task. Navigating to it from another task makes it usable, but navigating away leaves it undiscoverable again.
The trigger remains the cross-host duplicate described above. Desktop logs captured sidebar metadata requests trying to resolve a Windows cwd through the Remote SSH host before the stale object was archived. After archival, task routing became local, but the renderer did not rebuild its host-filtered sidebar projection.
Therefore the archive workaround is only partial:
The remaining renderer/sidebar failure matches #33579. This suggests that a cross-host identity collision can leave stale client-side sidebar state even after the catalog ambiguity is removed.
No rollout, database, or persisted pin record was modified. Private identifiers, task content, project names, paths, addresses, and hostnames are omitted.