fix(native): propagate edge/node write failures out of run_pipeline#1972
Conversation
insert_edges, build_and_insert_call_edges, and Stage 5's do_insert_nodes call all discarded their Result via `let _ =` (or an unchecked () return for insert_edges), so a transaction that never started or failed to commit left run_pipeline returning Ok(...) over an incomplete graph. NativeDatabase::build_graph then reported a "successful" build to JS with nothing beyond a stderr eprintln to show for it. Thread the Result through all three call sites via `?` so a write failure aborts run_pipeline and surfaces as a thrown napi error. tryNativeOrchestrator already catches that and falls back to the JS/WASM pipeline, so this turns a silent partial build into a real retry. Fixes #1827
Greptile SummaryThis PR makes native graph write failures visible to callers. The main changes are:
Confidence Score: 5/5This looks safe to merge after checking the partial import-edge retry behavior.
crates/codegraph-core/src/domain/graph/builder/stages/import_edges.rs Important Files Changed
Reviews (1): Last reviewed commit: "fix(native): propagate edge/node write f..." | Re-trigger Greptile |
| return Err(format!( | ||
| "insert_edges: {} of {total_chunks} chunk(s) failed to insert: {}", | ||
| chunk_failures.len(), | ||
| chunk_failures.join("; ") | ||
| )); | ||
| } | ||
| Ok(()) | ||
| } |
There was a problem hiding this comment.
When one import-edge chunk fails, this path commits the successful chunks and only then returns Err. The native caller now throws and the JS fallback runs against the same database, so the fallback can see a graph that already contains some of the new import edges while the rest of the native stages were skipped; because the edge table has no content-level uniqueness, retry insertion can leave duplicate or mixed edge rows instead of a clean rebuild.
Summary
run_pipeline(the fully-native build orchestrator,crates/codegraph-core/src/domain/graph/builder/pipeline.rs) silently discarded theResultfrom three edge/node-writing call sites, so a transaction that never started (or never committed) left the pipeline returningOk(...)over an incomplete graph:import_edges::insert_edges— onconn.unchecked_transaction()failure, previously dideprintln!(...); return;from a function returning(). Now returnsResult<(), String>.build_and_insert_call_edges(and its helperinsert_call_edge_rows) — called without capturing/checking its return value at all. Now returnsResult<(), String>and its caller propagates it.insert_nodes::do_insert_nodes(...)call — waslet _ = do_insert_nodes(...), explicitly discarding theResult. Now propagated via?.None of these bubbled up through
run_pipeline'sResult<BuildPipelineResult, String>, soNativeDatabase::build_graph()(the napi entry point) returned success to JS even when a transaction failed to start (e.g. transientSQLITE_BUSYunder WAL contention). The only observable symptom was an easily-missedeprintln!to stderr.Fix
Thread the
Resultfrom all three call sites up throughrun_pipelinevia?.NativeDatabase::build_graphalready.map_errsrun_pipeline's error into a thrown napi error, andtryNativeOrchestrator(the JS caller) already catches that and falls back to the JS/WASM pipeline — so a write failure now triggers a real retry instead of a silently-successful build over incomplete data.insert_edgeskeeps its existing per-chunk resilience (one malformed chunk doesn't sacrifice the rest of the batch) but now also returnsErrwhen any chunk failed, or when the transaction couldn't start/commit, instead of only warning to stderr.Since
commit_file_hashesruns after edge insertion, a write failure here now aborts the pipeline beforefile_hashesis touched — preserving the self-healing coupling from #1731 (an un-advanced hash means the next build retries the file), and now also making the current build's failure visible to the caller instead of reporting false success.Test plan
cargo test --release(codegraph-core crate) — 532 passed, 0 failedimport_edges.rsforinsert_edges: commits + returnsOkon success, returnsOkfor an empty batch, and returnsErrwhen the transaction can't start (regression test for this issue, using a nestedBEGINto force a deterministic transaction-start failure)cargo clippy --release— no new warnings introduced by this changenpx napi build --platform --release, codesigned), swapped it intonode_modules/@optave/codegraph-darwin-arm64, and verified the native build lifecycle end-to-end: full build, no-op incremental rebuild, and single-file incremental rebuild all behave identically to before this changenpx vitest run tests/builder/pipeline.test.ts tests/integration/— 915 passed (2 unrelated Lua/CLI-timeout failures confirmed to be resource-contention flakiness from the large parallel batch; both pass individually)npm run lint— clean (no TS/JS files touched)npm test(full suite) — 3679 passed; the only failures are 82 tests across verilog/objc/julia/dynamic-groovy, all traced vianpm run doctorto 7 optional WASM grammars missing from this fresh worktree (a known, pre-existing, non-blocking environment gap — seesrc/infrastructure/doctor.ts, unrelated to this change)Fixes #1827
Stacked on #1825/#1826 (base branch
fix/issue-1825-renamed-import-used-as-a-receiver-import-x-as) — only the two Rust files touched by this issue's fix are in this diff.