fix(resolution): filter stale-target edges so watch sync survives FK violations (#455)#463
Merged
Merged
Conversation
…violations (#455) PR #62 plugged this FK violation at the extraction-layer insertEdges site (empty-named nodes whose containment edges had no target), but the same violation kept reappearing on v0.9.5 during the daemon's *watch sync* once an agent's daemon had been running long enough. The resolution-layer insertEdges (and the callback-synthesizer pass) wasn't guarded the same way: a per-resolver name cache or a framework resolver's WeakMap-keyed lookup map could hand back a Node whose row had been removed by a recent file rewrite, and the FK check then aborted the entire resolution batch, leaving the daemon log filling with `Watch sync failed { error: 'FOREIGN KEY constraint failed' }`. The resolution layer now mirrors the #62 defense — one cache-aware getNodesByIds per pass drops any edge whose source or target is no longer in the nodes table, so the rest of the resolved batch still lands. Regression test seeds the resolver's nameCache with a stale Node and calls resolveAndPersist directly; verified to throw FOREIGN KEY constraint failed without the fix and pass with it. Full suite: 984/984 pass. Closes #455. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
colbymchenry
added a commit
that referenced
this pull request
May 26, 2026
…ives FK violations (#455) (#463)" This reverts commit 1dfaf30. Switching to #462's approach — a single, lower-layer filter inside QueryBuilder.insertEdges itself instead of three filters spread across the resolution layer. The DB-layer filter protects every caller (current and future) automatically and doesn't depend on the queries-layer nodeCache invalidation staying perfect. See #455 for the bug. The CHANGELOG entry for the user-facing fix is re-added on top of #462.
Owner
Author
jorgerobles
pushed a commit
to jorgerobles/codegraph
that referenced
this pull request
Jun 1, 2026
…violations (colbymchenry#455) (colbymchenry#463) PR colbymchenry#62 plugged this FK violation at the extraction-layer insertEdges site (empty-named nodes whose containment edges had no target), but the same violation kept reappearing on v0.9.5 during the daemon's *watch sync* once an agent's daemon had been running long enough. The resolution-layer insertEdges (and the callback-synthesizer pass) wasn't guarded the same way: a per-resolver name cache or a framework resolver's WeakMap-keyed lookup map could hand back a Node whose row had been removed by a recent file rewrite, and the FK check then aborted the entire resolution batch, leaving the daemon log filling with `Watch sync failed { error: 'FOREIGN KEY constraint failed' }`. The resolution layer now mirrors the colbymchenry#62 defense — one cache-aware getNodesByIds per pass drops any edge whose source or target is no longer in the nodes table, so the rest of the resolved batch still lands. Regression test seeds the resolver's nameCache with a stale Node and calls resolveAndPersist directly; verified to throw FOREIGN KEY constraint failed without the fix and pass with it. Full suite: 984/984 pass. Closes colbymchenry#455. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jorgerobles
pushed a commit
to jorgerobles/codegraph
that referenced
this pull request
Jun 1, 2026
…ives FK violations (colbymchenry#455) (colbymchenry#463)" This reverts commit 62975e3. Switching to colbymchenry#462's approach — a single, lower-layer filter inside QueryBuilder.insertEdges itself instead of three filters spread across the resolution layer. The DB-layer filter protects every caller (current and future) automatically and doesn't depend on the queries-layer nodeCache invalidation staying perfect. See colbymchenry#455 for the bug. The CHANGELOG entry for the user-facing fix is re-added on top of colbymchenry#462.
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
Fixes #455 —
FOREIGN KEY constraint failedduring watch sync on v0.9.5.PR #62 plugged this FK at the extraction-layer
insertEdgessite (empty-named nodes whose containment edges had no target). The same violation kept reappearing during the daemon's watch sync because the resolution-layerinsertEdges(inresolveAndPersist/resolveAndPersistBatched/synthesizeCallbackEdges) wasn't guarded the same way.Root cause. The resolution layer trusts resolver lookups to return live node IDs, but some framework resolvers (e.g.
react-native.ts,swift-objc.ts,rust.ts) cache nativeNoderefs in aWeakMap<ResolutionContext, …>that persists across watch syncs. A file rewrite between map build and resolution leaves dangling IDs in those caches — one bad edge fails FK, the transaction aborts, the daemon logsWatch sync failed.Fix. Mirror PR #62's pattern at the resolution layer: a small
filterEdgesByExistingNodeshelper runs one cache-awaregetNodesByIdsper batch and drops edges whose source or target is no longer in thenodestable. Applied at all three resolution-layer insert sites.Test plan
__tests__/sync-fk-regression.test.tswith two cases:nameCachewith aNodewhoseidisn't in the DB and callsresolveAndPersist— the exact failure mode FOREIGN KEY constraint failed during watch sync (v0.9.5 — regression from #28/#42/#53) #455 reports. Verified to throwFOREIGN KEY constraint failedwithout the fix and pass with it.npm run buildclean.🤖 Generated with Claude Code