fix(cli): sync says why it did nothing and exits non-zero - #1889
Closed
danusha2345 wants to merge 3 commits into
Closed
danusha2345 wants to merge 3 commits into
danusha2345 wants to merge 3 commits into
Conversation
When another process holds `.codegraph/codegraph.lock` (an MCP server or another CLI mid-index), `CodeGraph.sync()` returned all-zero counts and the CLI printed "Already up to date" and exited 0 — or, with `--quiet`, printed nothing — without having synced anything. `SyncResult` now carries `skippedReason: 'locked'` (plus the holder's PID when readable) and the CLI maps it to one stderr line with the reason and the remedy, exiting 1 in both normal and `--quiet` mode. Quiet suppresses progress, never a failure. The stale-extraction half of the same symptom is covered by colbymchenry#1842 and is deliberately not duplicated here. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…err count The test spawns the CLI with CODEGRAPH_WASM_RELAUNCHED=1, which skips the relaunch and with it --disable-warning=ExperimentalWarning. On Node 22 the node:sqlite ExperimentalWarning then lands on stderr as two extra lines and the quiet case, which expects exactly one line, fails (seen in CI on Node 22; Node 24 no longer warns). NODE_NO_WARNINGS=1 for the spawned CLI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
inth3shadows
left a comment
Contributor
There was a problem hiding this comment.
I tested this on Linux with Node 22, merged onto current main. cli-sync-reports-reason passes (5 of 5 runs). The git hooks codegraph installs run codegraph sync in the background with output sent to /dev/null, so the new exit 1 can't break git operations.
Two small points:
- Every lock failure is reported as contention.
sync()catches anyfileLock.acquire()failure and reports it aslocked. Repro: make.codegraph/codegraph.locka directory and runcodegraph sync -q. This branch prints "Nothing synced: another process holds the index lock. Retry…" and exits 1, even though no process holds it.mainexits 0. I'd setskippedReason: 'locked'only for real contention, and keep thecodegraph unlockhint the original lock error gave. - The changelog claim doesn't hold for the installed hooks. The entry says a failing git hook will show why. The hooks codegraph installs discard both output and exit status, so it only applies to user-written hooks.
… otherwise Review on colbymchenry#1889: sync() reported any failure to take the index lock as contention. A directory where codegraph.lock should be made sync print "another process holds the index lock" and exit 1 when nothing held it. Contention is now a live process named in the lock file (`locked`, with its PID); any other failure is `lock-failed` and carries the lock's own message, with its `codegraph unlock` hint. The changelog no longer says a failing git hook shows why: the hooks codegraph installs discard both output and exit status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Thanks, both points addressed in bd957c4:
Full suite: 4723 passed, 11 skipped. |
danusha2345
pushed a commit
to danusha2345/codegraph
that referenced
this pull request
Sep 27, 2026
… otherwise Review on colbymchenry#1889: sync() reported any failure to take the index lock as contention. A directory where codegraph.lock should be made sync print "another process holds the index lock" and exit 1 when nothing held it. Contention is now a live process named in the lock file (`locked`, with its PID); any other failure is `lock-failed` and carries the lock's own message, with its `codegraph unlock` hint. The changelog no longer says a failing git hook shows why: the hooks codegraph installs discard both output and exit status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
danusha2345
pushed a commit
to danusha2345/codegraph
that referenced
this pull request
Sep 27, 2026
Contributor
Author
|
Closing in favour of #2014, which landed the same fix: sync now surfaces lock contention, exits 1 and names the holder. The one difference is that upstream keeps |
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.
Symptom
When another process holds
.codegraph/codegraph.lock— an MCP server (daemon or directserve --mcp) running its own sync, or another CLI mid-index —CodeGraph.sync()catches the lock failure and returns all-zero counts. The CLI then printsAlready up to dateand exits 0; with--quiet(the git-hook path) it prints nothing and exits 0. Nothing was synced.Fix
SyncResultgains a structuredskippedReason: 'locked'(pluslockHolderPidwhen the lock file is readable), set only on the lock-acquisition failure path insync(). Library / watcher callers that ignored the zero result keep working unchanged.The CLI maps that reason to one stderr line and exits 1 in both modes:
--quietsuppresses progress, never a failure — so a hook that fails the commit on exit 1 still shows the user why.FileLock.readHolderPid()is a small read-only accessor so the message can name the holder; the foreign lock is left untouched.Relation to #1842
#1842 (
fix(cli): reject sync for stale extraction indexes) covers the other half of the same "sync looks successful but did nothing" symptom — an index built by an older extraction version. This PR deliberately does not duplicate that; it covers only the writer-lock case. The two are independent and can land in either order (the only shared file issrc/bin/codegraph.ts, non-overlapping hunks in the samesyncaction).Verification
npx tsc --noEmit -p tsconfig.jsonclean.__tests__/cli-sync-reports-reason.test.ts(5 tests):sync()reportsskippedReason: 'locked'with the holder PID;codegraph syncandcodegraph sync --quietexit 1 with the reason on stderr (quiet: exactly one stderr line, empty stdout), do not printAlready up to date, do not touch the lock file or the index; both modes sync normally once the lock is gone.mcp-writer-lock,git-index-currency,sync, and everycli-*.test.tsmentioning sync — 14 files, 131 tests passed (Linux, Node 22).🤖 Generated with Claude Code