Desktop (macOS): "failed to initialize sqlite state runtime" when another Codex app-server holds logs_2.sqlite (not corruption, not size)

Open 💬 3 comments Opened Jun 25, 2026 by BryanTegomoh

Summary

On native macOS, Codex Desktop fails to launch with the blocking dialog "Codex cannot access its local database" / failed to initialize sqlite state runtime under ~/.codex. The trigger is concurrent access: a second Codex app-server (a Codex IDE extension, an older build) was holding ~/.codex/logs_2.sqlite open, which prevented the Desktop app-server from initializing the SQLite state runtime within the startup handshake.

Both state_5.sqlite and logs_2.sqlite pass PRAGMA integrity_check (ok) and initialize fine in isolation — so this is neither corruption nor (purely) size. This is likely the same underlying cause as #27741 and #28666, but observed on native macOS and pinpointing multi-client / shared-CODEX_HOME concurrency as the trigger.

Environment

  • Codex Desktop for macOS, version 26.623.30605 (build 4415)
  • Bundled codex-cli 0.142.2
  • macOS 26.5.1, Apple Silicon (arm64)
  • Default ~/.codex on the internal APFS volume (not WSL, no /mnt/network mount)
  • Several Codex clients run against the same ~/.codex (Desktop app, Codex IDE extensions, and the codex CLI), each spawning its own ephemeral app-server (the app-server daemon is not enabled)

User-visible failure

Codex cannot access its local database.
...
Error: (code=1, signal=null).
Most recent error: Error: failed to initialize sqlite state runtime under
~/.codex: failed to initialize state runtime at ~/.codex

Desktop logs show the handshake child exiting code=1 repeatedly, ~5–8 s per attempt:

initialize_handshake_result durationMs=7308 ... outcome=failure
reason="Error: failed to initialize sqlite state runtime under ~/.codex: failed to initialize state runtime at ~/.codex"

One internal tracing line surfaced during a failed init: WARN ... slow statement: execution time exceeded alert threshold.

Root cause (reproduced)

  1. lsof ~/.codex/logs_2.sqlite showed another Codex app-server (a Codex IDE extension's, an older build) holding it (+ -wal, -shm) open continuously. state_5.sqlite had no holders.
  2. Driving the bundled app-server directly reproduces it:

printf '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}\n' | CODEX_HOME=~/.codex codex app-server → exits 1 with the same error.

  1. Bisection (all on codex-cli 0.142.2):
  • Fresh empty CODEX_HOME → init succeeds
  • Fresh home + real state_5.sqlite (170 MB) → succeeds
  • Fresh home + real logs_2.sqlite (1.14 GB) → succeeds (init < 10 s)
  • All four real DBs together + real config.tomlsucceeds
  • Real ~/.codex while another app-server holds logs_2.sqlitefails
  • Kill that app-server (freeing logs_2.sqlite), retry against real ~/.codexsucceeds (durationMs ≈ 450)
  1. PRAGMA integrity_check on both state_5.sqlite and logs_2.sqlite = ok.

So the state DBs are healthy; the Desktop app-server simply cannot acquire the access it needs to logs_2.sqlite during init while another (often older-version) app-server holds it, and the init aborts within the startup handshake budget.

Impact

Desktop refuses to launch entirely whenever another Codex client (IDE extension / CLI / another app-server) happens to be running against the same ~/.codex. The dialog advises "Close other Codex applications," but it is not obvious that a background IDE-extension app-server counts, and the heavier "Back Up and Rebuild" is unnecessary because the DB is fine.

Workaround

Free logs_2.sqlite instead of rebuilding:

lsof ~/.codex/logs_2.sqlite     # find the holding app-server PID(s)
kill <pid>                      # stop them
# relaunch Desktop

No data is moved or lost.

Suggestions

  1. Tolerate concurrent app-servers. The state runtime should coexist with other app-servers (shared WAL readers, or coordinate via the app-server daemon / single-writer with graceful waiting) instead of aborting the Desktop handshake.
  2. Surface the leaf cause. On macOS the error collapsed to a generic "failed to initialize state runtime at ~/.codex" with no underlying SQLite error (contrast #28666, which shows (code: 5) database is locked). Including the underlying SQLite/sqlx error (busy / locked / pool timeout) in the dialog and logs would make this self-diagnosable.
  3. Targeted recovery. When only logs_2.sqlite is the blocker, offer a "retry after releasing the logs DB" / recreate-just-the-logs-DB path (cf. #24001) rather than the full Back Up and Rebuild.

Related: #27741, #28666, #24006, #24001, #21750.

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗