Skip to content

ocx sync refuses Codex injection with generic history_injection_preflight_unavailable when state_5.sqlite is a WAL store with no live writer (-shm absent) #4943

Description

@tizerluo

Client or integration

Codex App

Area

CLI

Summary

ocx sync refuses the Codex config injection with the generic history_injection_preflight_unavailable whenever the Codex state database (~/.codex/state_5.sqlite) is in WAL journal mode with no live writer connected (no -shm/-wal sidecar files present). In that state a read-only SQLite connection cannot initialize WAL shared memory, so new Database(resolvedPath, { readonly: true }) inside preflightCodexHistoryInjection throws SQLITE_CANTOPEN (14), which the catch-all in src/codex/inject.ts (historyPreflight) folds into the generic "preflight unavailable" refusal.

Expected: the preflight should still be able to inspect the store — immutable=1 reads work fine and the preflight only runs PRAGMA table_info(threads) plus a SELECT rollout_path, history_mode FROM threads, so a lock-free read is safe — or at minimum report a distinct failure reason so operators can tell "store is fine, preflight could not open it read-only" apart from a genuinely unreadable store. The store itself is healthy; the refusal blocks model_catalog_json from reaching config.toml on every sync attempt until a workaround is applied.

Reproduction

  1. macOS + ChatGPT desktop (Codex) used at least once, so ~/.codex/state_5.sqlite exists; quit the app cleanly (sidecar -wal/-shm are removed on clean close; verify with ls ~/.codex/state_5.sqlite*).
  2. Confirm the store is WAL and readable without locks:
    • sqlite3 "file:$HOME/.codex/state_5.sqlite?immutable=1" "PRAGMA journal_mode; SELECT COUNT(*) FROM threads;"wal, row count (store healthy)
    • sqlite3 "file:$HOME/.codex/state_5.sqlite?mode=ro" "SELECT COUNT(*) FROM threads"Error: in prepare, unable to open database file (14) ← the exact condition the preflight hits
  3. Run ocx sync.
  4. Observe the refusal (logs below); Codex sync did not complete and config.toml keeps the previous model_catalog_json (no damage, but the transition never converges).

Workaround we currently use: hold one read-write connection open for the duration of the sync (e.g. Python sqlite3.connect(path) kept alive while ocx sync runs, then close). The -shm then exists, the read-only preflight joins it, and sync completes normally (rc=0, + 440 models appended to Codex catalog). This suggests a targeted fix inside the preflight would work: on SQLITE_CANTOPEN for a WAL store, retry with immutable=1 (or open briefly read-write to create the shared memory), or surface a dedicated reason code instead of the generic one.

Code pointers (2.58.0): src/codex/history-provider.ts preflightCodexHistoryInjection()db = new Database(resolvedPath, { readonly: true }); src/codex/inject.ts historyPreflight()catch { return "history_injection_preflight_unavailable"; }.

Version

2.58.0

Operating system

macOS 26 (Tahoe) 25.6, Apple Silicon (arm64)

Provider and model

Not provider-specific (Codex state store access).

Logs or error output

$ ocx sync
Codex config injection refused: history_injection_preflight_unavailable. Existing provider definitions and conversation files were preserved. Paginated history requires native-writer coordination; do not run legacy recovery or retry this transition blindly.
   Target Codex home: /Users/[USER]/.codex
Codex sync did not complete. Fix the reported Codex config issue and retry.

$ sqlite3 "file:$HOME/.codex/state_5.sqlite?mode=ro" "SELECT COUNT(*) FROM threads"
Error: in prepare, unable to open database file (14)

$ sqlite3 "file:$HOME/.codex/state_5.sqlite?immutable=1" "PRAGMA journal_mode; SELECT COUNT(*) FROM threads;"
wal
2465

Redacted configuration

Not config-dependent; environment facts: ocx 2.58.0, codex-cli 0.154.0 (source=configured), CODEX_HOME=/Users/[USER]/.codex, state store state_5.sqlite (valid SQLite format 3 header, threads table present with 2465 rows).

  • I searched existing issues and documentation.
  • I removed secrets, tokens, account details, request credentials, and personal data.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcliCLI, config inject, packaging flags

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions