Desktop launch can fail when logs_2.sqlite grows large: app-server SQLite pool times out during startup
Summary
Codex Desktop on Windows can fail to launch when the local diagnostic log SQLite database (logs_2.sqlite) grows large enough that app-server startup cannot initialize the SQLite runtime within the Desktop handshake timeout.
This is related to the existing logs_2.sqlite growth/WAL reports, but the user-visible failure mode is different: Desktop shows a blocking "Codex cannot access its local database" dialog even though state_5.sqlite is healthy. Moving only logs_2.sqlite* aside lets app-server recreate the logs DB and launch normally without touching threads, goals, memories, sessions, or config.
Environment
- Product: Codex Desktop for Windows
- Windows Store package observed in logs:
OpenAI.Codex_26.609.3341.0_x64 - Bundled WSL CLI observed:
codex-cli 0.140.0-alpha.2 - Mode: Desktop app-server running in WSL
- Config shape:
runCodexInWindowsSubsystemForLinux = trueintegratedTerminalShell = "wsl"sqlite_home = "/mnt/c/Users/<WindowsUser>/.codex"- SQLite home is on the Windows-backed
/mnt/cfilesystem.
User-visible failure
On launch, Desktop showed:
Codex cannot access its local database.
Database path: Path unavailable in app-server startup error
Error: (code=1, signal=null).
Most recent error: Error: failed to initialize sqlite state runtime under
/mnt/c/Users/<WindowsUser>/.codex: failed to initialize state runtime at
/mnt/c/Users/<WindowsUser>/.codex: pool timed out while waiting for an open connection
Desktop never finished launching until the logs DB was moved aside.
Log evidence
Sanitized Desktop log sequence:
Launching app ... package OpenAI.Codex_26.609.3341.0_x64
[wsl] eligible distro list ... Ubuntu Running 2
stdio_transport_spawned executablePath=C:\Users\<WindowsUser>\.codex\bin\wsl\<hash>\codex spawnCommand=wsl.exe
Initialize handshake still pending durationMs=10020
app_server_connection.closed code=1 reason="Error: failed to initialize sqlite state runtime under /mnt/c/Users/<WindowsUser>/.codex: failed to initialize state runtime at /mnt/c/Users/<WindowsUser>/.codex: pool timed out while waiting for an open connection"
initialize_handshake_result durationMs=33522 outcome=failure
Retrying spawned a second app-server process and failed the same way after about 33 seconds.
Local DB evidence
Before recovery:
state_5.sqlite ~35.6 MB
logs_2.sqlite ~4.5 GB
logs_2.sqlite-wal ~1.08 GB
logs_2.sqlite-shm ~1.47 MB
goals_1.sqlite small
memories_1.sqlite small
Read-only checks:
state_5.sqlite quick_check: ok
goals_1.sqlite quick_check: ok
memories_1.sqlite quick_check: ok
logs_2.sqlite was the outlier:
- A simple metadata query against
logs_2.sqlitetook about 45 seconds. select count(*) from logstook about 38 seconds and returned about 862,750 rows.min(id), max(id)showed heavy churn: max row id was above 100M.- WAL-aware
pragma quick_checkdid not finish within 120 seconds. - An immutable read-only check reported freelist / pointer-map errors, but because immutable mode ignores WAL frames this should be treated as corruption-suspicious rather than definitive corruption.
Recovery experiment
The following was tested without touching thread/session state:
- Stop Codex Desktop / app-server.
- Move only these files out of the active
.codexdirectory into a backup folder:
``text``
logs_2.sqlite
logs_2.sqlite-wal
logs_2.sqlite-shm
- Leave all of these in place:
``text``
state_5.sqlite
goals_1.sqlite*
memories_1.sqlite*
sessions/**
archived_sessions/**
session_index.jsonl
config.toml
auth files
plugin/cache/config files
- Start the same app-server binary against the same real Codex home.
Result:
- app-server startup succeeded.
- A fresh
logs_2.sqlitewas recreated at about 48 KB. - Fresh
logs_2.sqlitepassedquick_check. - Existing
state_5.sqlitestill passedquick_check. - Thread/session files were not moved or edited.
This strongly indicates the launch blocker was the diagnostic logs DB path, not the actual thread/state DB.
Likely root cause
From the public source shape, StateRuntime::init opens/migrates state, logs, goals, and memories DBs as part of app-server startup. It also runs log startup maintenance:
delete logs older than retention window
PRAGMA wal_checkpoint(PASSIVE)
When logs_2.sqlite and/or its WAL are multi-GB and slow on /mnt/c, this work can exceed the startup/connection pool/handshake timeout. The resulting error bubbles up as a generic SQLite state runtime failure, which makes it look like the main thread database is inaccessible even when state_5.sqlite is healthy.
Expected behavior
- A large, slow, or damaged diagnostic log DB should not prevent Desktop from launching.
- Startup should not synchronously block on log retention/checkpoint work that can take tens of seconds or minutes.
- If the logs DB is unhealthy or too slow, Codex should rotate/regenerate it automatically or offer a safe "clear diagnostic logs" recovery path.
- The error dialog should identify the specific DB that failed (
logs_2.sqlitevsstate_5.sqlite) and explain whether conversation history is at risk. - Log maintenance should be bounded, backgrounded, and non-fatal where possible.
Suggested fixes
- Treat log DB initialization/maintenance as non-critical for app launch when state DB opens successfully.
- Add a bounded timeout around log startup maintenance, and defer heavy
DELETE/ checkpoint work until after Desktop is usable. - Add automatic rotation of
logs_N.sqlite*when the file or WAL exceeds a threshold. - Configure WAL limits/checkpointing/retention so the diagnostic DB cannot grow to multi-GB under normal Desktop/goal/app-server usage.
- Surface a safe recovery button/action: "Move diagnostic logs aside and relaunch".
- Improve diagnostics so the dialog reports the actual failing DB path and classifies
statevslogsvsgoalsvsmemories.
Related issues
- #26374 - app-server feedback log SQLite grows unbounded
- #24275 - Desktop rapidly grows
logs_2.sqlite/ WAL during normal active use - #17320 - excessive SQLite WAL writes during streaming / TRACE logging
- #22444 - stale Codex processes keep huge deleted
logs_2.sqlite-walallocated - #21134 - Desktop becomes unusable on long active threads with TRACE log churn
- #27395 - Desktop
turn/starttimes out while app-server sidecar stalls - #25715 - Windows Desktop with WSL mode suffers severe performance issues on Windows-backed
.codex
This issue is intended to capture the specific launch-blocking failure and recovery path, not to duplicate the broader log-growth reports.
10 Comments
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Update from 2026-06-22 on Windows Desktop + WSL2.
Same launch-blocking class reproduced on newer Desktop builds, but the user-visible dialog now says:
Sanitized log evidence:
Local DB evidence:
wal_checkpoint/truncate alone was not sufficient; app-server still did not reach the listener after about 90 seconds.Recovery was again isolated to diagnostic logs:
logs_2.sqlite,logs_2.sqlite-wal, andlogs_2.sqlite-shmaside.state_5.sqlite, sessions, goals, memories, config, and auth state untouched.Result:
This reinforces that the startup blocker is diagnostic log DB initialization/maintenance, not conversation state corruption.
Potentially adjacent / compounding issue:
Which should have been fixed by:
Which were released in:
But there still seem to be issues after that:
Bounding the WAL + lowering write volume keeps the DB/WAL from reaching sizes that stall the startup pool: https://github.com/denispol/codex/pull/1
I hit what looks like the same issue with the VS Code Codex extension timing out over Remote SSH.
Environment:
Symptoms:
Database details:
So it looks like a combination of high log volume plus SQLite free pages not being reclaimed. Automatic log rotation, retention, or periodic VACUUM would probably prevent this.
Additional reproduction from macOS:
I had been running Codex more or less continuously during a month-long cutover. After restarting and upgrading, Codex Desktop failed with:
Codex app-server initialize handshake timed outThe relevant files were:
I fully stopped Codex, moved only
logs_2.sqlite*aside, and restarted. Startup was then effectively instantaneous. I did not movestate_5.sqlite, sessions, goals, memories, configuration, or authentication state.This looks like a predictable consequence of sustained operation rather than an unusual one-off corruption case. It may be worth placing an explicit bound on diagnostic-log storage and ensuring that log maintenance cannot block the app-server initialize handshake.
Possible safeguards:
Sharding by time period might also help, although bounded retention and rotation appear to be the underlying requirement.
Corroborating this on native macOS / APFS with the current ChatGPT/Codex desktop build, including a WAL-aware integrity failure in the diagnostic logs DB.
Environment
26.803.61601(build6396)codex-cli 0.147.0-alpha.6.525A5349a), Apple Silicon / arm64~/.codexon internal APFSSanitized launch sequence (UTC)
11:36:07— desktop spawned bundled app-server.11:36:37— initialize remained pending for exactly30001ms, then failed withCodex app-server initialize handshake timed out.11:36:51— app-server exitedcode=1after6596mswith only:``
text
``failed to initialize sqlite state runtime under ~/.codex:
failed to initialize state runtime at ~/.codex
The nested SQLite/database name was not surfaced.
8875ms, with no repair, reset, DB move, reinstall, or settings change.The app bundle passed
codesign --verifyand Gatekeeper assessment; there was no macOS crash report. This was app-server bootstrap failure rather than an app binary crash.DB evidence immediately after recovery
Read-only checks:
state_5.sqlite:PRAGMA quick_check(1)->okoklogs_2.sqlite: WAL-awarePRAGMA quick_check(1)andPRAGMA integrity_check(10)both fail in root tree 5, which maps to thelogstable. Representative errors:``
text
``Tree 5 page 308797 cell 0: Failed to read ptrmap key=218103808
Tree 5 page 308797 cell 0: invalid page number 218103808
Tree 5 page 215710 cell 0: Bad ptr map entry ...
Tree 5 page 230651 cell 0: 2nd reference to page 156436
There was still about 22.6 GiB available and no
ENOSPCevidence. I did not mutate, checkpoint, vacuum, rebuild, or move any DB.Interpretation
This instance appears to be a large and structurally unhealthy diagnostic
logs_2database gating desktop startup, while the actual conversation/state DB remains healthy. The recovery without intervention makes the failure intermittent: one attempt timed out, the immediate retry produced the generic SQLite-runtime error, and a later retry initialized successfully despite the unhealthy logs DB remaining in place.Because the app-server error drops the leaf cause/database path, I cannot prove which startup statement hit the corrupt pages. It would help if startup:
logs_2.sqlitefailure as non-fatal or recreated only that diagnostic DB safely;~/.codex/ state runtime;This also overlaps the generic macOS symptom in #30105, but unlike that report, this case has direct WAL-aware integrity errors in
logs_2.sqlite; I am therefore adding it here rather than opening a duplicate.Same symptom and same workaround here (Windows,
OpenAI.Codex26.810.7004.0), but the underlying cause turned out to be corruption rather than size. Filed separately as #39015.logs_2.sqlitewas 2.27 GB with a 1.05 GB WAL, so it looked exactly like this report — butquick_checkshowed the B-tree was actually malformed:Two observations that may matter for this thread:
The WAL was regenerated on every launch, not replayed. After an unrelated checkpoint left it at 132 frames, a single launch rebuilt it to 274,060 frames (+1.05 GB in ~38 s) before timing out. An earlier failed launch that morning produced 274,306 frames — two runs, ±0.1%. That is deterministic work against a fixed damaged structure, not accumulated history.
Checkpointing therefore does not help. We tested it inadvertently: the WAL went to 33 frames, and the very next launch regenerated 274,060 and failed identically. A corrupt B-tree cannot be checkpointed into health, which is why only moving the file aside works.
Might be worth asking reporters on this thread to run an integrity check before size thresholds get tuned — if some fraction of these are corruption rather than growth, a size-based rotation cap wouldn't fix them. It's non-destructive and takes about 30 seconds:
immutable=1matters — it bypasses the WAL and all locking, so the result reflects the file itself and is unaffected by any running app-server.Either way, the suggestion in this issue — treat log DB initialisation as non-critical when the state DB opens successfully — would have prevented the outage in both the size case and the corruption case.
Hi @MisterRound, cross-platform WSL/Windows path mismatches often make healthy transcripts look broken when workspace contexts change. Codex Rescue Alpha5 explicitly separates transcript integrity from workspace path-family portability without rewriting saved paths.
If you'd like to check the local rollout safely:
Please sanitize private paths before posting any output.
Regarding the
logs_2.sqliteWAL pool timeout blocking desktop startup:Your root cause analysis is spot on. When
StateRuntime::initattempts a synchronousPRAGMA wal_checkpoint(PASSIVE)across multi-gigabyte WAL logs on cross-VFS mounts (e.g./mnt/c), SQLite transaction contention exceeds the RPC handshake window and kills the connection pool.If you encounter this startup blocker, Vetto includes automated session diagnostic and WAL recovery tools for Codex:
How Vetto handles SQLite state recovery:
logs_*.sqlite) from user conversation state (state_*.sqlite), ensuring broken log files never lock thread histories.