Regression: macOS migration clones installation identity and Remote Control fails with 409

Open
#36,295 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
42/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
macos, rust, sqlite

Research direction

Start by reviewing the migration steps and the persisted files ~/.codex/installation_id, ~/.codex/.codex-global-state.json, and ~/.codex/state_5.sqlite, then reproduce the 409 Remote Control response. Trace how the cloned identity and enrollment state are handled; done should mean migrated devices recover through a supported flow without manual JSON or SQLite edits and show a useful error.

Written by the indexing model from the issue text.

Description

app bug connectivity remote
What version of the Codex App are you using?

ChatGPT desktop app with bundled Codex:

  • App version: 26.727.40816
  • Bundle build: 6067
What subscription do you have?

Not relevant to the failure; the same ChatGPT account was used on both Macs.

What platform is your computer?
  • Destination: Mac mini (Mac16,10), Apple Silicon (arm64)
  • macOS 26.6 (25G72)
  • Source: MacBook Pro
  • The destination Mac was migrated from the source Mac using macOS Migration Assistant / copied user data.

Real hostnames and all account, installation, environment, server, request, and key identifiers are intentionally redacted.

What issue are you seeing?

After migrating from a MacBook Pro to a Mac mini, enabling Settings > Connections > Control this Mac > Allow connections failed. The toggle returned to the off state and the desktop app showed:

Couldn't update remote control availability

The app server repeatedly attempted to connect to:

wss://chatgpt.com/backend-api/wham/remote/control/server

and received:

HTTP error: 409 Conflict
body: {"detail":"Remote app server already online"}

Only one ChatGPT desktop process and one bundled Codex app-server process were running locally when checked, so this was not caused by two active local app-server processes.

The source and destination Macs had inherited the same machine-scoped identity from:

~/.codex/installation_id

Historical local logs showed the same installation identity being used first by the source Mac and later by the destination Mac, despite different hostnames. The backend therefore treated the two physical Macs as the same Remote host.

Signing out was not a recovery mechanism: signing out affected both devices, and signing back in did not regenerate the local installation identity. A normal app reinstall would also be expected to preserve ~/.codex, so it does not provide an obvious fresh-device path. Existing projects still appeared after sign-in because the local project/thread state was preserved; this is expected but makes it less clear to a user that the machine identity was also preserved.

This appears to be a regression or still-unhandled case of #22950 on a substantially newer app build. It is also related to the stale-enrollment 409 Conflict behavior in #24024, but the trigger here was machine migration and a cloned installation_id, not idle time or a network transition.

What steps can reproduce the bug?
  1. Install and use ChatGPT/Codex on a source Mac with Remote Control enrolled.
  2. Migrate the source Mac's user account/data to a second Mac using macOS Migration Assistant or another mechanism that copies ~/.codex.
  3. Keep or later run ChatGPT/Codex on both physical Macs under the same ChatGPT account.
  4. On the migrated destination Mac, open Settings > Connections > Control this Mac.
  5. Enable Allow connections.
  6. Observe the generic Couldn't update remote control availability toast.
  7. Inspect ~/.codex/logs_2.sqlite and observe repeated 409 Conflict responses with {"detail":"Remote app server already online"}.
  8. Compare ~/.codex/installation_id on both physical Macs and observe that Migration Assistant cloned the machine-scoped identity.
Workaround that resolved the issue

The recovery was performed only on the migrated destination Mac.

  1. Fully quit ChatGPT/Codex and related Remote/app-server processes on both Macs.
  2. Back up the relevant local files:
~/.codex/installation_id
~/.codex/.codex-global-state.json
~/.codex/state_5.sqlite
  1. Move aside the migrated identity:
mv ~/.codex/installation_id <backup-location>/installation_id.migrated
  1. Clear only the persisted Remote Control enrollment rows, preserving the rest of the thread/project database:
sqlite3 ~/.codex/state_5.sqlite "DELETE FROM remote_control_enrollments;"
  1. Remove the mirrored local Remote host identity keys from ~/.codex/.codex-global-state.json:
electron-local-remote-control-installation-id
electron-local-remote-control-environment-id

The client/controller enrollment keys were not intentionally removed.

  1. Restart ChatGPT/Codex on the destination Mac.
  2. The app generated a different ~/.codex/installation_id, created one fresh Remote enrollment row, and the global-state installation ID matched the new file.
  3. Enable Allow connections again.
  4. The next observed Remote websocket result was connected; the repeated 409 loop stopped.

The workaround preserved local projects, chats/threads, plugins, and general Codex configuration.

What is the expected behavior?
  • A machine-scoped installation identity should not be silently cloned onto different physical hardware during Migration Assistant restore.
  • On startup, Codex should detect that a persisted installation identity is running on materially different hardware and either regenerate it or prompt the user.
  • Receiving 409 Conflict: Remote app server already online for a migrated/cloned identity should trigger a safe re-enrollment flow instead of indefinite retries and a generic availability toast.
  • Settings should provide a supported Repair Remote Control or Reset this device identity action.
  • Signing out or reinstalling should clearly explain whether local device enrollment is preserved.
  • Recovery should not require manually editing JSON or SQLite.
  • The error shown in Settings should distinguish duplicate device identity from network, authentication, workspace-policy, or permission failures.
Related issues
  • #22950 — same Migration Assistant / duplicated ~/.codex/installation_id root cause; closed as completed on an older build
  • #24024 — related persistent 409 Conflict / stale enrollment family; different trigger
Additional confirmation after recovery
  • The destination Mac's regenerated installation identity differs from the migrated identity.
  • The global-state mirror matches the new identity.
  • Exactly one fresh Remote enrollment row exists.
  • The latest Remote Control websocket event is a successful connection.

This report intentionally omits raw identifiers and credentials. Sanitized logs with timestamps or request IDs can be provided privately if maintainers need them.

Dominant language
Rust
Stars
125k
Forks
19.5k
Avg merge
1m
Merged PRs (30d)
1k

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from openai/codex

All issues in openai/codex

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.