fix: SCIP enrichment duplicate-PK crash, COPY bad-record retry, ENOSPC preflight - #44
Open
pradeepmouli wants to merge 1 commit into
Open
fix: SCIP enrichment duplicate-PK crash, COPY bad-record retry, ENOSPC preflight#44pradeepmouli wants to merge 1 commit into
pradeepmouli wants to merge 1 commit into
Conversation
…C preflight Root-causes the sittir 43GB SCIP-enrichment bloat/crash incident: - scip_sym_to_name (crates/infigraph-core/src/scip/mod.rs) had two bugs that produced colliding or garbled symbol names: it didn't handle a double-quote-quoted descriptor with a trailing disambiguator digit (e.g. `"'"0`), and it didn't handle a chained non-empty `(...)` disambiguator group after a method's own empty parens (e.g. `findNestedSeparator().(rule).`), which fell through to returning the raw unparsed SCIP symbol string as the name. Both now fold the disambiguator into the returned name instead of discarding it, preventing the primary-key collision that crashed the COPY. - Replaced the "COPY fails -> fall back to per-row UNWIND for the whole batch" pattern everywhere it occurred (SCIP's Symbol/CALLS/INHERITS, the main indexer's edge-table loop, resolve/calls.rs, resolve/inherits.rs) with a bounded drop-bad-record-and-retry-COPY heuristic: parse the offending value out of Kuzu's own COPY error text, drop just that record, and retry the bulk COPY (up to 20 attempts) before falling back to UNWIND. - Added a disk-headroom preflight before SCIP's bulk writes (GraphStore::db_dir + store_util::check_disk_headroom, using the existing fs2 dependency). lbug throws an uncaught C++ TransactionManagerException on ENOSPC mid-transaction, aborting the whole process rather than surfacing a Rust Result -- this preflight turns that into a graceful error instead. Also confirmed (not a code change): all 4 write-capable paths -- SCIP enrichment, full reindex, incremental index/watch, and cross-file resolve -- already acquire GraphStore::write_lock() independently, so the incident was not a locking gap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SjmvwHuwV5r7ZeZpJLp5oR
pradeepmouli
requested review from
johnintuit,
murari316 and
sandeep-mewara
as code owners
July 30, 2026 04:29
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Root-causes a crash observed in a real-world SCIP-enrichment run:
scip_sym_to_namehad two bugs that produced colliding or garbled symbol names, which crashed the bulkCOPYinsert with a primary-key collision.scip_sym_to_name(crates/infigraph-core/src/scip/mod.rs) didn't handle:"'"0, used by scip-typescript for non-identifier term names like string-literal object keys)(...)disambiguator group after a method's own empty parens (e.g.findNestedSeparator().(rule).), which fell through to returning the raw, unparsed SCIP symbol string as the "name"Both now fold the disambiguator into the returned name instead of discarding it — dropping it collapsed genuinely distinct symbols onto the same extracted name, causing the primary-key collision that crashed the
COPY.Bad-record-drop-and-retry heuristic. Replaced the "
COPYfails → fall back to slow per-rowUNWINDfor the whole batch" pattern everywhere it occurs (SCIP's Symbol/CALLS/INHERITS inserts, the main indexer's edge-table loop,resolve/calls.rs,resolve/inherits.rs) with a bounded drop-bad-record-and-retry-COPYheuristic: parse the offending value out of Kuzu's ownCOPYerror text, drop just that record, and retry the bulkCOPY(up to 20 attempts) before falling back toUNWIND. Avoids paying the slow per-row path for an entire batch over a handful of bad rows.Disk-headroom preflight before SCIP's bulk writes. Kuzu throws an uncaught C++
TransactionManagerExceptionon ENOSPC mid-transaction, aborting the whole process rather than surfacing aResult. Added a preflight check (GraphStore::db_dir+store_util::check_disk_headroom, using the already-presentfs2dependency) that refuses gracefully with a normal error instead.Also hardened a pre-existing flaky assertion in
crates/infigraph-mcp/tests/groups_watch_perf.rs(group_indexcan legitimately report "Indexed 0 repos" if background auto-watch already indexed both repos by the time the explicit call runs — both outcomes mean the data is indexed).Test plan
cargo test -p infigraph-core --lib— 284/284 passing (includes 4 new regression tests for the twoscip_sym_to_namebugs, plus tests for the newextract_bad_copy_value/check_disk_headroomhelpers)cargo test -p infigraph-mcp --test groups_watch_perf -- --ignored— verified across multiple runs after the assertion fixcargo test -p infigraph-core --test write_lock_perf -- --ignored— passingcargo test -p infigraph-core --test index_perf -- --ignored— passingcargo fmt --all -- --checkandcargo clippy --all-targets -- -D warnings— clean🤖 Generated with Claude Code
https://claude.ai/code/session_01SjmvwHuwV5r7ZeZpJLp5oR