Skip to content

bug(native): bulkInsertNodes corrupts DB when JS and Rust connections coexist #696

@carlos-alm

Description

@carlos-alm

Problem

When both better-sqlite3 (JS) and rusqlite (Rust) connections are open to the same WAL-mode database file, NativeDatabase.bulkInsertNodes() corrupts the DB. Subsequent reads from either connection fail with SqliteError: database disk image is malformed or disk I/O error.

Context

The native insert path in insert-nodes.ts was never operational — it always crashed during napi-rs serialization due to null visibility values being passed to Option<String> fields (fixed in #693). Once the serialization was fixed, the Rust code actually executed for the first time and revealed the dual-connection WAL corruption.

Reproduction

In CI (where the native binary is available), any test that calls buildGraph with engine: 'native' triggers the issue:

  • tests/builder/pipeline.test.tsSQLITE_CORRUPT when reading after native insert
  • tests/integration/build.test.tsdisk I/O error on incremental rebuilds

All pass locally when only the WASM engine is available (native path falls through to JS).

Root cause

The build pipeline holds ctx.db (better-sqlite3) and ctx.nativeDb (rusqlite NativeDatabase) open simultaneously. Both connect to the same .codegraph/graph.db file in WAL mode. When rusqlite writes inside bulkInsertNodes, it may conflict with the JS connection's WAL state.

Fix options

  1. Close the JS connection before calling native insert, reopen after
  2. Route all pipeline writes through the native connection when available (remove dual-connection pattern)
  3. Use exclusive locking mode for the native transaction

Workaround

PR #693 disables tryNativeInsert when ctx.db is open (which is always the case in the pipeline), restoring the pre-existing JS-only behavior.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions