Skip to content

fix(db): probe WAL support and fall back to DELETE on unsupported filesystems (#990)#1177

Open
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix-990-wal-fallback
Open

fix(db): probe WAL support and fall back to DELETE on unsupported filesystems (#990)#1177
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix-990-wal-fallback

Conversation

@maxmilian

Copy link
Copy Markdown
Contributor

Fixes #990.

Problem

configureConnection (src/db/index.ts) sets journal_mode = WAL unconditionally. On filesystems where mmap(MAP_SHARED) returns EOPNOTSUPP on the WAL-index — ntfs3, WSL2 /mnt, some CIFS/NFSPRAGMA journal_mode = WAL reports "wal" but the first write fails with SQLITE_IOERR, and the connection is already corrupted (switching to another mode afterwards also fails). The user-visible symptom is codegraph init dying with disk I/O error.

SQLite does not silently fall back here — it reports WAL as active and then fails on write.

Fix

  • Add walAvailable(dir): opens a throwaway database in the target directory, runs PRAGMA journal_mode = WAL plus a real CREATE/DROP write (the write is what actually exercises the WAL-index mmap), and cleans up its probe files. Returns false on any failure.
  • configureConnection(db, useWal) now takes an explicit flag. When useWal is false it falls back to journal_mode = DELETE with synchronous = FULL (NORMAL is only crash-safe under WAL).
  • The two call sites (initialize, open) compute useWal = walAvailable(dir).

The probe goes through the existing createDatabase adapter, so it honors whatever backend the connection would actually use.

Note: the issue proposed editing the compiled lib/dist/db/index.js; this PR fixes the TypeScript source src/db/index.ts instead, which is where the build output comes from.

Testing

__tests__/wal-fallback.test.ts (all green, 72 tests pass across the touched suites):

  • walAvailable returns true on a normal writable dir and leaves no probe files behind;
  • walAvailable returns false when the directory can't host a database;
  • configureConnection(db, true)journal_mode = wal;
  • configureConnection(db, false)journal_mode = delete and writes still succeed (the point of the fallback);
  • DatabaseConnection.initialize produces a working WAL database on a normal fs.

Honest limitation: the actual EOPNOTSUPP path can't be reproduced on APFS (macOS), so these tests exercise the branching + the DELETE-mode write path rather than forcing a real mmap failure. The reporter's syscall trace (mmap MAP_SHARED errno=95) plus their ntfs3/btrfs/ext4 repro substantiate the failure mode itself. Happy to add a Linux/ntfs3 CI matrix probe if that's wanted.

…esystems (colbymchenry#990)

configureConnection set journal_mode=WAL unconditionally. On filesystems where
mmap(MAP_SHARED) returns EOPNOTSUPP for the WAL-index (ntfs3, WSL2 /mnt, some
CIFS/NFS), PRAGMA journal_mode=WAL reports "wal" but the first write fails with
SQLITE_IOERR and the connection is already corrupted, so `codegraph init` dies
with "disk I/O error".

Probe WAL on a throwaway database up front (walAvailable) and only enable it on
the real connection when the probe survives an actual write; otherwise fall back
to DELETE mode with synchronous=FULL. configureConnection now takes an explicit
useWal flag computed at the two call sites.
@maxmilian maxmilian force-pushed the fix-990-wal-fallback branch from f4708a2 to 7120da1 Compare July 5, 2026 14:05
@maxmilian maxmilian marked this pull request as ready for review July 5, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WAL: auto-detect filesystem mmap support and fall back to DELETE mode

1 participant