Windows Desktop WSL app-server fails to launch due to CRLF/LF SQLx migration checksum mismatch

Resolved 💬 11 comments Opened May 20, 2026 by MisterRound Closed Jun 12, 2026
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

26.519.2081.0

What subscription do you have?

Pro

What platform is your computer?

Microsoft Windows NT 10.0.26200.0 x64

What issue are you seeing?

Upgraded Codex Desktop from Windows Store (with Codex Desktop app closed), fails to launch.

Codex CLI (not desktop app) says:

Root Cause
Your state_5.sqlite was initialized/migrated with CRLF SQL migration bytes. The updated Desktop app is launching a WSL/Linux Codex app-server
whose embedded migrations use LF bytes. SQLx migration checksums are byte-for-byte, so it treats the same SQL text with different line endings as
“migration modified.”

Evidence:

  • Your DB _sqlx_migrations rows 1..31 all match sha384(CRLF(upstream migration SQL)).
  • The upstream rust-v0.131.0 migration files hash differently as LF.
  • Local Windows binaries embed CRLF migration text.
  • Local Linux/WSL binaries embed LF migration text.
  • Desktop logs show the failing app launches:

C:\Users\xxx\.codex\bin\wsl\7945a00f33bdc140\codex

  • That WSL binary is codex-cli 0.131.0, and it rejects the CRLF-checksummed DB at migration 1.

Why It Started Now
Upstream commit 53a36fc1c changed app-server startup to hard-fail if the state DB cannot be opened. So this mismatch became a launch-blocking
error instead of a softer degraded state.

Relevant upstream links:

Recovery Implication
This is not DB corruption. It is a cross-platform migration checksum bug caused by line endings.

Now that we know all 31 checksums are CRLF-vs-LF only, a controlled repair path exists: update _sqlx_migrations.checksum from CRLF hashes to LF
hashes for versions 1..31, after backup. That is still a DB edit, but it is much less scary now because the SQL content is semantically identical;
only line endings differ. I would only do it against the live DB after testing the exact update on a copied backup and proving the updated copy
opens with the failing WSL binary.

<img width="1104" height="624" alt="Image" src="https://github.com/user-attachments/assets/c633acc4-abf8-4c66-abb4-5e3a20767178" />

What steps can reproduce the bug?

Update Codex from Windows store, try to launch Codex

What is the expected behavior?

Codex updates and then launches new version without issue or error message at launch

Additional information

_No response_

View original on GitHub ↗

11 Comments

github-actions[bot] contributor · 2 months ago

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

  • #23251

Powered by Codex Action

MisterRound · 2 months ago

Follow-up after controlled recovery testing on a copied database and then live recovery:

Confirmed root cause remains CRLF/LF migration checksum mismatch, not database corruption or a lock.

Additional findings:

  • state_5.sqlite was not the only affected SQLx-managed DB. logs_2.sqlite also had _sqlx_migrations.checksum values matching CRLF-normalized migration SQL, while the WSL/Linux app-server expected LF-normalized migration SQL.
  • The Desktop app was configured to run Codex in WSL and launched the WSL/Linux app-server. That app-server rejected the Windows-created CRLF checksums.
  • state_5.sqlite rows 1..31 matched CRLF hashes of the upstream state migrations. After converting those checksum blobs to the LF hashes, the WSL app-server progressed far enough to apply the next state migration (0032_threads_preview) and then failed on logs_2.sqlite for the same reason.
  • logs_2.sqlite rows 1..2 matched CRLF hashes of the upstream logs migrations. After converting those checksum blobs to LF hashes too, the WSL app-server smoke test no longer hit the migration error and Codex Desktop launched successfully.

Validation performed before/after repair:

  • Full backup taken before any live DB change.
  • Reproduced the failure against an unmodified disposable copy.
  • Applied checksum-only repair to a disposable copy first.
  • Verified pragma integrity_check stayed ok.
  • Verified user/data table row counts were unchanged in the disposable test.
  • Verified all repaired migration checksums matched LF hashes from upstream migration files.
  • Verified Desktop-launched WSL app-server path no longer exits with migration 1 was previously applied but has been modified.

Important compatibility note:

This repair makes the DB compatible with the WSL/Linux app-server path. Windows-native Codex binaries still appear to embed CRLF migration bytes and may reject the LF-repaired DB unless the product normalizes migration line endings or accepts both historical checksum forms. For affected users, do not blindly edit SQLite state; take a full backup first and test on a copy.

Suggested product-side fix:

Normalize SQL migration bytes before SQLx checksum calculation across platforms, or add a one-time compatibility path for existing databases whose migration checksums equal the CRLF form of the exact same migration SQL.

z3nitsu · 2 months ago

Facing the same issue here

MisterRound · 2 months ago
Facing the same issue here

I got it resolved, use Codex CLI standalone (I use it in WSL) and just give it the full issue and my follow up comment and it should be able to fix it, it's working now

xdifu · 2 months ago

@MisterRound — your CRLF/LF root cause is more precise than the "OpenAI modified the migration SQL in place" theory in my parallel write-up at #23787. I can confirm it from independent evidence: I extracted all 34 SHA-384 anchors directly from my own 0.131.0-alpha.9 WSL backend ELF (%USERPROFILE%\.codex\bin\wsl\<hash>\codex) by scanning the binary for (sql, sha384(sql)) byte-adjacency anchors, and every single one matches sha384(LF(<upstream rust-v0.131.0 migration SQL>)) byte-for-byte. Anyone with the same backend version can reproduce: python codex-repair.py extract-checksums --json and diff against the source migrations.

Two complementary observations that may be worth tracking alongside your CRLF/LF finding:

  1. Bug B — 30 s GUI backfill timeout (separate but adjacent). Even after the CRLF→LF checksum patch makes Codex Desktop's WSL backend launch successfully, the GUI imposes a hard-coded 30 s wait for state_5.sqlite.backfill_state.status='complete', while the backend's own backfill lease is 900 s (per #11377). On any install with > ~100 MB of session history (mine: 3.5 GB across 365 sessions), the WSL backend reads sessions/*.jsonl via 9P over /mnt/c/ — 5–10× slower than native ext4 — and routinely exceeds 30 s. The error you'd hit next is timed out waiting for state db backfill at ... after 30s (status: running). Full repro + manual-backfill workaround in #23787.
  1. Schema-compatibility guardrail. Regardless of whether the fix is CRLF→LF or a future genuine SQL change, the safest in-place patch is: parse the binary-expected migration SQL, run PRAGMA table_info(<table>) on the live DB, confirm every expected column already exists, and only then UPDATE _sqlx_migrations SET checksum = ?. That avoids the failure mode where someone naively rewrites a checksum on a DB whose schema is actually older than the binary expects.

---

Reusable recovery toolkit

For anyone landing here from search, I've packaged both fixes (plus the schema-verify guardrail) into a standalone Apache-2.0 Python toolkit: https://github.com/xdifu/codex-repair

Windows PowerShell / Windows Terminal:

# One-shot diagnose:
python codex-repair.py doctor

# One-shot fix (backs up DBs, schema-verifies, then rewrites the CRLF→LF checksums + repairs backfill):
python codex-repair.py fix --apply

If you run it from WSL bash to repair Windows Codex Desktop data, pass --codex-home "/mnt/c/Users/<WindowsUser>/.codex" so it does not target WSL's own ~/.codex.

What it does for you, automatically:

  • Auto-detects the backend binary at %USERPROFILE%\.codex\bin\wsl\*\codex (no hard-coded version constants — works for any future Codex Desktop binary).
  • Extracts the binary's LF-hashed migration checksums dynamically by scanning the ELF for (sql, sha384(sql)) byte-adjacency anchors. Means it'll keep working when OpenAI ships 0.132, 0.133, etc., even if those binaries embed yet another checksum set.
  • Diffs against _sqlx_migrations in both state_5.sqlite and logs_2.sqlite.
  • Schema-verifies via PRAGMA table_info(<table>) before any write — refuses to rewrite a checksum if the live schema is actually older than the binary expects.
  • Takes timestamped DB backups (.bak-fix-checksums-YYYYMMDDHHMMSS) before any mutation.
  • Has a --use-isolated-copy mode that operates on temp copies of the DBs — safe to run for diagnosis even while Codex Desktop is still open.
  • Includes a manual-backfill subcommand that parses sessions/**/*.jsonl first-line session_meta headers, inserts the threads rows the backend would have inserted, and marks backfill_state.status='complete' — bypassing the 30 s GUI cap entirely.

Conversation history (~/.codex/sessions/*.jsonl) is read-only the whole time. The toolkit only ever writes to the two SQLite metadata DBs, and always with backup + transaction.

Cross-linking #23787 here so users hitting either symptom find both perspectives.

---

Suggested upstream fix (echoing yours): normalize SQL migration bytes before sqlx::migrate!() hashes them — include_str!(...).replace("\r\n", "\n") at compile time, or a build.rs step that rewrites .sql files to canonical LF form before compilation. That single change prevents every future CRLF/LF drift on every platform without any client-side shim. As a one-shot compatibility patch, the migrator's VersionMismatch arm could also try sha384(CRLF(SQL)) before failing — that would clear every existing affected install in the wild without anyone having to install a third-party tool.

JustinJLeopard · 2 months ago

Adding an independent data point with the opposite drift direction.

Same release as this issue and #23787 — Codex Desktop 26.519.2081.0 (May 20 build). The release bundle ships both line-ending variants side by side:

  • app\resources\codex.exe (Windows-native, 238MB) — embedded migration SQL uses CRLF
  • app\resources\codex (Linux ELF for the WSL backend, 221MB) — embedded migration SQL uses LF

Verified by mmap inspection of both binaries (b'CREATE TABLE threads' snippet: 6 CRLF in the .exe, 0 CRLF in the ELF).

My install hits the inverse of @MisterRound and @xdifu's direction:

  • _sqlx_migrations rows held checksums equal to SHA-384(LF(<new SQL>)) — LF-side from a prior binary.
  • Codex Desktop on launch invoked the Windows-native binary (CRLF). Runtime hash mismatched.
  • Recovery was the inverse mapping: patch all 31 state_5.sqlite + 2 logs_2.sqlite checksums from LF to CRLF (SHA-384(<exact CRLF bytes in resources\codex.exe>)). After patch, Codex launched cleanly and the new 0032_threads_preview migration applied forward.

So the affected population splits along which backend Codex Desktop actually invokes on each user's machine (WSL ELF vs Windows-native .exe), and the same release bundle is internally inconsistent in line endings between those two binaries. Whatever upstream fix lands needs to be symmetric — both directions are reachable from a single release. xdifu's codex-repair toolkit covers the WSL-backend direction; the Windows-native direction's mapping is the inverse of the table @MisterRound posted above. Happy to share the per-migration LF→CRLF table if useful.

Juberstine · 2 months ago

Same issue

hsbtr · 2 months ago

I have the same issue. In the previous version, the agent's operating environment was in WSL. After the upgrade, this problem occurred. Then, after I tried multiple times, the data was lost. The update of this version is disappointing.

mattlgroff · 1 month ago

I left feedback in the app and here's the feedback id for any openai employees looking here no-active-thread-019e5bd6-3995-7302-8448-b1fec39d1b92

MisterRound · 1 month ago

Follow-up triage note from the same Windows Desktop + WSL update incident.

This issue remains a distinct and real startup failure: the SQLx migration checksum mismatch blocked launch before any thread recovery could happen. After that was recovered locally, a separate failure surfaced when resuming the previous long-running /goal thread: the rollout had grown to multi-GB size and Desktop/app-server became unavailable during resume/goal recovery.

I opened that separate root-cause issue as #25215 so this issue can stay focused on the update/startup database compatibility problem.

Relationship between the issues:

  • #23777: update/startup failure caused by SQLx migration checksum mismatch in Windows Desktop + WSL mode.
  • #25215: post-startup failure where /goal can grow a rollout beyond practical Desktop resume/recovery limits.
  • #25216: umbrella issue for Windows Desktop + WSL release-gate coverage across config, state, plugins, exec, and recovery.

All local paths/usernames remain redacted in the public reports.

ax-openai · 1 month ago

Closing as a duplicate of #23251.