Codex mobile shows macOS host offline/stuck when state_5.sqlite threads table is malformed

Open 💬 7 comments Opened May 18, 2026 by ntharvey-rgb
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

Summary

Codex mobile Remote Control stopped working for a macOS Codex Desktop host that had worked the previous day. ChatGPT iOS showed the macOS host as offline / last seen hours ago, and later showed the same host with a spinner and loading placeholders. The macOS host was online, Codex Desktop was running, firewall was disabled, and the desktop app was up to date.

Local investigation found ~/.codex/state_5.sqlite is corrupt, specifically the threads table/indexes. Desktop logs repeatedly report sqlite state db unavailable while trying to update thread metadata. This appears to make mobile Remote Control surface a stale/offline/loading state instead of detecting local state DB corruption and showing a repairable error.

Environment

  • Codex Desktop: 26.513.31313 / bundle 2867
  • Bundled CLI: codex-cli 0.131.0-alpha.9
  • Host OS: macOS 26.3.1 (a) build 25D771280a
  • Host arch: arm64
  • Mobile: ChatGPT iOS Codex Remote Control
  • Host identity/IDs intentionally redacted

What happened

  1. Codex mobile Remote Control worked normally the previous day.
  2. The next day, ChatGPT iOS showed the macOS host as offline / last seen hours ago.
  3. Tapping reconnect did not restore it.
  4. Reopening the mobile surface later showed the host name with a spinner and loading placeholders.
  5. On the Mac, Codex Desktop was running and responsive.
  6. macOS firewall was disabled.
  7. The app bundle was current according to the appcast.
  8. Local remote-control enrollment still existed in ~/.codex/state_5.sqlite.
  9. lsof showed the Codex app server had outbound HTTPS connections; this did not look like a LAN listener/firewall issue.
  10. The failing local state DB was then checked directly with SQLite.

Diagnostics

sqlite3 ~/.codex/state_5.sqlite 'pragma integrity_check;' returns:

Error: stepping, database disk image is malformed (11)
*** in database main ***
Tree 5 page 147: btreeInitPage() returns error code 11
Tree 36 page 129: btreeInitPage() returns error code 11
Tree 35 page 131: btreeInitPage() returns error code 11
Tree 34 page 34: btreeInitPage() returns error code 11
Tree 33 page 33: btreeInitPage() returns error code 11
Tree 24 page 24: btreeInitPage() returns error code 11
Tree 23 page 23: btreeInitPage() returns error code 11
Tree 22 page 22: btreeInitPage() returns error code 11
Tree 21 page 21: btreeInitPage() returns error code 11
Tree 20 page 20: btreeInitPage() returns error code 11
wrong # of entries in index idx_threads_archived_cwd_updated_at_ms
wrong # of entries in index idx_threads_archived_cwd_created_at_ms
wrong # of entries in index idx_threads_updated_at_ms
wrong # of entries in index idx_threads_created_at_ms
wrong # of entries in index idx_threads_provider
wrong # of entries in index idx_threads_source
wrong # of entries in index idx_threads_archived
wrong # of entries in index idx_threads_updated_at
wrong # of entries in index idx_threads_created_at
wrong # of entries in index sqlite_autoindex_threads_1

The affected rootpages correspond to threads and its indexes.

Desktop logs contain repeated failures like this, with thread IDs redacted here:

2026-05-17T19:28:50Z error [electron-message-handler] Request failed ... error={"code":-32603,"message":"failed to update thread metadata: thread-store internal error: sqlite state db unavailable for thread <redacted>"} method=thread/metadata/update
2026-05-18T02:11:59Z error [electron-message-handler] Request failed ... error={"code":-32603,"message":"failed to update thread metadata: thread-store internal error: sqlite state db unavailable for thread <redacted>"} method=thread/metadata/update

A SQLite .recover against a snapshot of the DB completed successfully, and the recovered DB passes pragma integrity_check with ok. The recovered DB retained the remote_control_enrollments row. Recovery has not yet been applied to the live install at the time of filing.

Expected behavior

If Codex Desktop finds that state_5.sqlite is malformed or that threads is unavailable:

  • Desktop should surface a clear local recovery/repair message instead of leaving mobile to show the host as offline or stuck loading.
  • Mobile Remote Control should show a specific actionable error, for example that the desktop host is online but local state is corrupted/unavailable.
  • Codex should preserve the malformed DB, rebuild/recover from session JSONL where possible, and re-index threads automatically or via a visible repair action.
  • Remote-control host health should distinguish between transport/connectivity failure and local state-store failure.

Actual behavior

The phone shows the host as offline/stale or stuck loading, even though the desktop host is running. The local SQLite corruption is only discoverable by manually running pragma integrity_check and reading desktop logs.

Related issues

This looks related to both:

  • #20493, which reports corrupt state_5.sqlite causing desktop chats to disappear/blank.
  • #22773, which tracks broader iOS/macOS Remote Control stale/offline/hydration failures.

This report is narrower: a malformed threads table/indexes in state_5.sqlite appears to make mobile Remote Control present the macOS host as offline/stuck rather than reporting a local state-store failure.

Privacy note

This report intentionally omits account IDs, server/environment IDs, raw hostnames, screenshots, full local paths outside ~/.codex, and thread IDs.

View original on GitHub ↗

7 Comments

github-actions[bot] contributor · 2 months ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #22898
  • #22942

Powered by Codex Action

ntharvey-rgb · 2 months ago

Follow-up: after quitting Codex, backing up ~/.codex/state_5.sqlite*, recovering the SQLite DB with .recover, replacing state_5.sqlite, and removing the old WAL/SHM files, mobile Remote Control started working again.

Post-repair checks:

sqlite integrity_check: ok
remote_control_enrollments row still present for Codex Desktop
fresh Codex desktop logs after restart: no new `sqlite state db unavailable` matches observed

This confirms that the malformed threads table/indexes in state_5.sqlite were at least sufficient to cause the observed mobile offline/stuck behavior.

Snailflyer · 2 months ago

The follow-up confirming .recover fixed mobile Remote Control is useful because it separates transport health from local state-store health.

For remote control, the host should probably publish a small health vector instead of one generic online/offline state:

  • app-server reachable
  • remote enrollment present
  • thread store readable
  • selected thread metadata readable
  • relay/mobile path connected

In this case the host was online, but threads was not a reliable data source. Showing that as offline/stale on mobile sends the user toward network and pairing fixes, when the actionable fix is local state repair/reindex.

dreamerlyq-arch · 2 months ago

A simple solution for anyone who encounters this issue in future: simply send this text to Codex and ask them to sort it out:

Help me fix Codex CLI remote-control installation and connectivity on macOS. Do not modify any project files. You may only operate in my home directory, shell config, Codex install directories, and temp directories.

Please execute directly and do not stop to ask questions unless absolutely necessary.

Goals:
1. Determine which `codex` binary my shell is actually using.
2. Check whether the standalone install required by `codex remote-control` exists.
3. Diagnose why the terminal cannot download `https://chatgpt.com/codex/install.sh`.
4. If direct access fails, inspect system proxy settings and terminal proxy env vars.
5. If a system proxy exists, explicitly reuse it for `curl` and for the installer.
6. If no env proxy is present, try common local proxy ports.
7. Download the installer to a temp file first, verify it is a real shell script and not an HTML error page.
8. Run the installer.
9. Confirm that `~/.codex/packages/standalone/current/codex` exists.
10. Run `codex remote-control`.
11. If it fails, clearly classify the failure as one of:
   - DNS issue
   - direct TCP 443 connectivity issue
   - proxy not injected into terminal
   - TLS/certificate issue
   - wrong installer content downloaded
   - installer execution failure
   - remote-control runtime failure

Please follow this exact order:

1. Check environment:
   - `whoami`
   - `uname -a`
   - `zsh --version`
   - `node --version`
   - `npm --version`
   - `which codex`
   - `codex --version`
   - `echo $PATH`
   - `npm prefix -g`

2. Check standalone install:
   - `ls -la ~/.codex/packages/standalone/current/codex`
   - `ls -la ~/.codex/packages/standalone/current || true`
   - `ls -la ~/.codex/packages || true`

3. Download installer to a temp file, not via pipe:
   - `rm -f /tmp/codex-install.sh`
   - `curl -fL --connect-timeout 15 --max-time 45 https://chatgpt.com/codex/install.sh -o /tmp/codex-install.sh`
   - `ls -lh /tmp/codex-install.sh`
   - `head -40 /tmp/codex-install.sh`

4. If direct download fails, diagnose:
   - `curl -Iv --connect-timeout 15 --max-time 30 https://chatgpt.com`
   - `curl -Iv --connect-timeout 15 --max-time 30 https://chatgpt.com/codex/install.sh`
   - `scutil --proxy`
   - `env | grep -i proxy || true`
   - `networksetup -getwebproxy Wi-Fi || true`
   - `networksetup -getsecurewebproxy Wi-Fi || true`
   - `networksetup -getsocksfirewallproxy Wi-Fi || true`

5. If system proxy settings are found, explicitly reuse them for download and installer execution.

6. If no proxy env vars are available, try these common local proxy ports:
   - `7890`
   - `7897`
   - `7899`
   - `1080`
   - `1086`
   - `8080`
   - `6152`

   For each port, test both:
   - `http://127.0.0.1:PORT`
   - `socks5h://127.0.0.1:PORT`

7. If installer download succeeds:
   - show file size
   - show first lines
   - verify it is not HTML
   - then run:
     - `sh -x /tmp/codex-install.sh`

8. After install:
   - `ls -la ~/.codex/packages/standalone/current/codex`
   - `~/.codex/packages/standalone/current/codex --version || true`
   - `which codex`
   - `codex --version`

9. Then run:
   - `codex remote-control`

10. If `remote-control` still fails, stop and report the exact error. Do not keep trying random fixes.

At the end, summarize:
- root cause
- what you changed
- what commands succeeded
- what proxy settings should be exported in future shells if needed

If proxy export is needed, give me the exact commands, for example:
- `export HTTPS_PROXY=http://127.0.0.1:7890`
- `export HTTP_PROXY=http://127.0.0.1:7890`
- `export ALL_PROXY=socks5h://127.0.0.1:7890`
nelhu · 2 months ago

I ran into this issue too. Later I found that it was caused by a corrupted state_5.sqlite, which made codex app-server fail to start. In the end, I also had to reset remote_control so the app and client could reconnect properly and fully resolve the problem.

nelhu · 2 months ago
I ran into this issue too. Later I found that it was caused by a corrupted state_5.sqlite, which made codex app-server fail to start. In the end, I also had to reset remote_control so the app and client could reconnect properly and fully resolve the problem.

ChatGPT App Could Not Connect to Codex Desktop: A Remote Control Fix Caused by a Corrupted state_5.sqlite

One-Line AI Repair Prompt

This is the prompt I would give to Codex or Claude if I wanted it to repair the same problem end to end:

Help me diagnose and fix why ChatGPT App cannot connect to Codex Desktop Remote Control on this Mac. Do not modify any project files; only operate in my home directory, Codex install directories, and temporary directories. First confirm which codex binary is used, codex --version, the standalone binary, codex remote-control, and codex app-server daemon version. If ~/.codex/state_5.sqlite is corrupted, fully back up state_5.sqlite, state_5.sqlite-wal, and state_5.sqlite-shm first, then use sqlite3 .recover to create a recovered database. Only replace the original database after PRAGMA integrity_check returns ok. After repair, restart codex remote-control and confirm app-server-control.sock exists. Finally, clear remote_control_enrollments and reset app-server-control/app-server-daemon state so the phone and Mac can pair again. If any step cannot be verified, stop and report the exact error instead of trying random fixes.

Background

I recently ran into a strange issue: the ChatGPT mobile app could not connect to Codex Desktop running on my Mac. The Mac side looked fine. Codex Desktop could open normally, and nothing obvious suggested that the local client was broken.

At first, I suspected the usual suspects: mobile network, account state, proxy settings, or some connection issue between the phone and the Mac.

Then I found a very relevant GitHub issue: openai/codex#23247. The discussion there mentioned a similar symptom: the ChatGPT iOS app showed the macOS host as offline or stuck loading, while the local ~/.codex/state_5.sqlite database was malformed.

That matched the direction of my own failure, so I stopped looking only at the mobile app and started tracing the local codex remote-control path on the Mac.

Symptoms

On the phone, the symptom was simple: ChatGPT App could not connect to my Mac. It looked as if Codex Desktop was offline.

On the Mac, I first checked the basic client state:

which codex
codex --version
ls -la ~/.codex/packages/standalone/current/codex

The local codex command had already been switched to the standalone install:

/Users/<user>/.local/bin/codex
codex-cli 0.132.0

The real failure showed up when I ran:

codex remote-control

It failed with:

Error: app server did not become ready on /Users/<user>/.codex/app-server-control/app-server-control.sock

Caused by:
    0: failed to connect to /Users/<user>/.codex/app-server-control/app-server-control.sock
    1: No such file or directory (os error 2)

At this point, it looked like a missing socket problem, or maybe the app-server simply did not start. But after checking the daemon state more closely, I found that the missing socket was only the visible symptom. The app-server process was exiting during startup.

Root Cause

The root cause was a corrupted ~/.codex/state_5.sqlite database. Because of that, codex app-server failed while initializing the local state database, and remote-control never got far enough to create the control socket.

The key diagnostic command was:

sqlite3 ~/.codex/state_5.sqlite 'PRAGMA integrity_check;'

On my machine, it returned errors like:

Error: stepping, database disk image is malformed (11)
wrong # of entries in index idx_threads_archived_cwd_updated_at_ms
wrong # of entries in index idx_threads_archived_cwd_created_at_ms
wrong # of entries in index idx_threads_updated_at_ms
wrong # of entries in index idx_threads_created_at_ms
wrong # of entries in index sqlite_autoindex_threads_1

I also tried starting the app-server manually with a temporary Unix socket:

codex app-server --listen unix:///tmp/codex-test/app-server-control.sock

That exposed the error more directly:

failed to initialize sqlite state db at /Users/<user>/.codex/state_5.sqlite
database disk image is malformed

So I could basically rule out DNS, TCP 443 connectivity, TLS certificates, the mobile network, and the macOS firewall. The phone showed a connection failure, but the thing that was actually broken was the local Codex state database on the Mac.

How It Works

The misleading part is that the mobile app only shows the host as offline or unavailable. Locally, codex remote-control complains that a Unix socket does not exist. Both symptoms point away from the actual root cause.

The real chain looks like this:

vuon9 · 1 month ago

I tried to solve the same issue with gpt 5.5 medium and it found another root cause. I want to share it here so people can try.
My phone can connect to the destination mac, but my mac couldn't and it used to work.

Problem

Codex Desktop could discover another Mac, but starting a remote session failed. The stale device kept appearing, and discovery reused the same broken entry.

Logs showed: Remote-control client has been revoked

This was not the same root cause as issue #23247, because SQLite was healthy:

sqlite3 ~/.codex/state_5.sqlite 'pragma integrity_check;'

Expected:

ok

Cause

Codex had a stale local remote-control client enrollment stored in:

~/.codex/.codex-global-state.json
~/.codex/.codex-global-state.json.bak

The important key was:

electron-remote-control-client-enrollments

Deleting it only from the main file was not enough, because Codex could restore it from memory or the .bak file.

Fix

Quit Codex Desktop first:

osascript -e 'tell application "Codex" to quit'

Back up the state files:

cp ~/.codex/.codex-global-state.json ~/.codex/.codex-global-state.json.pre-remote-reset.bak
cp ~/.codex/.codex-global-state.json.bak ~/.codex/.codex-global-state.json.bak.pre-remote-reset.bak

Remove the stale enrollment from both files:

jq 'del(."electron-remote-control-client-enrollments")' \
~/.codex/.codex-global-state.json > /tmp/codex-global-state.json \
&& mv /tmp/codex-global-state.json ~/.codex/.codex-global-state.json

jq 'del(."electron-remote-control-client-enrollments")' \
~/.codex/.codex-global-state.json.bak > /tmp/codex-global-state.json.bak \
&& mv /tmp/codex-global-state.json.bak ~/.codex/.codex-global-state.json.bak

Verify:

for f in ~/.codex/.codex-global-state.json ~/.codex/.codex-global-state.json.bak; do
printf '%s ' "$f"
jq 'has("electron-remote-control-client-enrollments")' "$f"
done

Expected:

false
false

Reopen Codex Desktop.

Result

Settings → Connections → Control other devices should reset to the fresh setup flow. Click Set up, authorize on chatgpt.com, then discover/pair again.