Repository navigation
fix(cli): codegraph status opens the index read-only, and says when a rebuild is running - #2921
Closed
danusha2345 wants to merge 1 commit into
Closed
danusha2345 wants to merge 1 commit into
danusha2345 wants to merge 1 commit into
Conversation
… a rebuild is running Status opened the database read-write, so the open ran the writer's repairs: migrations, the FTS trigger and secondary-index recovery an interrupted bulk load leaves behind, WAL maintenance. During a `codegraph index` that recovery recreated the five edge indexes the indexer had dropped for its bulk load, and the indexer's next edge write, whose transaction had already read its endpoints, failed with SQLITE_BUSY_SNAPSHOT: "Failed to index: database is locked" (colbymchenry#2913). Status reads: it opens with `readOnly: true`, which leaves every repair to the writer, as the MCP reader connections already do. When another live process holds `rebuild.pid`, the report says so (`rebuildInProgress` in `--json`, a warning in the text), since its numbers are a snapshot of a graph being rebuilt. `isRebuildInProgress` is the check `assertNoRebuild` already made, exported for a caller that reports rather than refuses. The test runs the built CLI against an index whose writer holds a bulk edge load with both locks: status answers, the dropped indexes stay dropped, and the writer's edge insert succeeds; a read-write open still repairs them. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
colbymchenry
pushed a commit
that referenced
this pull request
Oct 27, 2026
… rebuild is running Status opened the database read-write, so its open ran the writer's repairs: migrations, the FTS-trigger and secondary-index recovery an interrupted bulk load leaves behind, and WAL maintenance. During a `codegraph index`, that recovery recreated the indexes the indexer had dropped for its bulk load, and the indexer's next write, whose transaction had already read, failed with SQLITE_BUSY_SNAPSHOT (517): "Failed to index: database is locked". Status now opens with `readOnly: true` and leaves every repair to the writer, as the MCP reader connections already do. When another live process holds `rebuild.pid`, it says so: a warning in the text output and `rebuildInProgress` in `--json`, the only new key. `isRebuildInProgress` is the check `assertNoRebuild` already made. Added when landing it: - A read-only open migrates nothing, so status on an index built by 1.4.0 or older (schema 7, no `unresolved_refs.status`) failed with "no such column: status". The pending-reference count counts every row when the column is missing, as the v8 migration marks them pending. - While a rebuild runs, status skips the advice meant for an index at rest: the interrupted-run references, "run sync", "re-index", and the oversized-WAL warning, which mid-rebuild all describe the live run. - Status no longer reclaims a killed session's oversized WAL, so the warning names the next `codegraph sync` instead of status itself. - Tests: the issue's exact interleaving (status inside the writer's edge transaction, as in PR #2916's test), a pre-v8 index, and the mid-rebuild advice. Validation (Windows 11, Node 22.22): - The issue's reproduction with our build of main 69af19a: status inside the transaction exits 0, the writer fails with errcode 517 and the five dropped edge indexes come back. With this change the insert succeeds and the indexes stay dropped. - Real rebuilds of excalidraw 95307fa1 (716 files) with `codegraph status` looping beside them, 3 with default settings and 3 with the resolution window forced: main failed 6 of 6, each with "store worker: database is locked" and an empty index; this change failed 0 of 6 over 46 status runs, with identical complete graphs (14,236 nodes, 61,210 edges). - status-during-rebuild.test.ts: 7/7 pass. With main's sources 6 of 7 fail; without `readOnly` 3 fail, one with "database is locked"; with the PR as written the pre-v8 and mid-rebuild cases fail. - Indexes built by v1.6.2 (schema 11) and v1.4.0 (schema 7): the same numbers as main, and the schema is left as it is. Interrupted-index warnings (indexing, partial, failed) are unchanged. Original PR #2921 by @danusha2345. Fixes #2913 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
|
Thanks @danusha2345! This landed in #2930 with you as the commit author: |
This was referenced Oct 27, 2026
danusha2345
pushed a commit
to danusha2345/codegraph
that referenced
this pull request
Oct 28, 2026
…mchenry#2972; 10 landed PRs yield to main; EXTRACTION_VERSION 56) Main landed ten more of our PRs as our own commits with the maintainer's additions (colbymchenry#2923 ← colbymchenry#1936, colbymchenry#2924 ← colbymchenry#1951, colbymchenry#2925 ← colbymchenry#1939, colbymchenry#2930 ← colbymchenry#2921, colbymchenry#2940 ← colbymchenry#1736, colbymchenry#2942 ← colbymchenry#1947, colbymchenry#2950 ← colbymchenry#1952, colbymchenry#2961 ← colbymchenry#1954, colbymchenry#2965 ← colbymchenry#1942, colbymchenry#2972 ← colbymchenry#1933) and the module-path half of colbymchenry#2308 (colbymchenry#2955). Where the integration carried our version, main's wins: the enclosing-scope member pick and its tests, the Go and Java receiver typers, the delegating-call self-loop rule, the duplicated-module copy confidence, the C #if collapse, the module-path resolution of Rust paths, the trail/path hardening in utils.ts. Kept beside main: colbymchenry#1875's Verilog hooks and status fields, colbymchenry#2839's implementations command, colbymchenry#1923, colbymchenry#2922, colbymchenry#2258, colbymchenry#1761, colbymchenry#1583, the bare-call half of colbymchenry#2308 (rust-use-bindings.ts). CHANGELOG is main's plus the open PRs' bullets. EXTRACTION_VERSION 56: the C #if group handling (colbymchenry#2940) and the kernel change. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.
Fixes #2913.
What happened
codegraph statusopened the database read-write, soDatabaseConnection.openran the writer's open-time repairs on it: migrations, the FTS-trigger and secondary-index recovery an interrupted bulk load leaves behind, WAL maintenance. While acodegraph indexwas running, that recovery recreated the five edge indexes the indexer had dropped for its bulk load (beginBulkEdgeLoad). The indexer's nextinsertEdgestransaction had already read its endpoint ids, so the schema change invalidated its snapshot and the write failed with SQLite extended code 517,SQLITE_BUSY_SNAPSHOT: "Failed to index: database is locked". The issue's reproduction, a writer in a bulk edge load that runs the realcodegraph statusbetween its endpoint read and its edge insert, shows exactly that; with{ readOnly: true }at the same point the writer succeeds.The change
CodeGraph.open(projectPath, { readOnly: true })). A read-only open skips migrations, bulk-load repair and WAL maintenance, as the MCP reader connections already do (Shared-daemon sessions lose CodeGraph with "writer lock held": stop() waits on an unregistered connection, and a blocked fallback refuses instead of reading (1.6.0) #1963), and everything status reads is a read.rebuild.pid,--jsoncarriesrebuildInProgress: trueand the text output warns that the numbers are a snapshot of a graph being rebuilt. The check is the oneassertNoRebuildalready made, exported asisRebuildInProgressfor a caller that reports rather than refuses; a lock left by a dead process is not a rebuild.Crash repair is unchanged: a read-write open, the writer's own, still recreates what an interrupted bulk load dropped.
Tests
__tests__/status-during-rebuild.test.ts(4 tests), against the built CLI as the issue's reproduction:rebuild.pidandwriter.pidnaming a live process;codegraph status --jsonanswers with the statistics andrebuildInProgress: true, the dropped indexes are still dropped afterwards, and the writer's edge insert succeeds;endBulkEdgeLoadbrings the indexes back;The first test fails on
mainat the index check (status recreated the five indexes).Full suite on
main69af19a with the native kernel (CODEGRAPH_KERNEL_EXPECT=1): 9,072 passed, 39 skipped, 0 failed;tsc --noEmitclean.🤖 Generated with Claude Code