abhigyanpatwari/GitNexus · warning
Structural relationship count failed; the graph-write-collap
Error message
Structural relationship count failed; the graph-write-collapse check will have no structural measurement from this run.
What it means
Post-load validation could not count structural relationships (the MATCH ()-[r:REL]->() WHERE NOT r.type IN [excluded] count over the rel table failed). By contract the count stays undefined rather than becoming a misleading 0 — a zero would read as a total wipeout to the graph-write-collapse guard. The failure reason is carried on the result as structuralEdgesError and logged here, so 'guard could not measure' is distinguishable from 'guard ran and found nothing'.
Source
Thrown at gitnexus/src/core/lbug/lbug-adapter.ts:1948
let structuralEdges: number | undefined;
let structuralEdgesError: string | undefined;
try {
const excluded = [...PDG_EDGE_TYPES].map((t) => `'${t}'`).join(', ');
structuralEdges = await withConnLock(async () => {
const queryResult = await c.query(
`MATCH ()-[r:${REL_TABLE_NAME}]->() WHERE NOT r.type IN [${excluded}] RETURN count(r) AS cnt`,
);
const rows = await readQueryRows(queryResult);
return rows.length > 0 ? Number(rows[0]?.cnt ?? rows[0]?.[0] ?? 0) : 0;
});
} catch (err) {
// Same contract as `edges`: leave undefined rather than report a zero the
// collapse check would read as a total wipeout. But NOT silent — the reason
// travels back on the result and is logged by the caller, so "the guard
// declined because it could not measure" is visible instead of looking
// identical to "the guard ran and found nothing wrong".
structuralEdgesError = err instanceof Error ? err.message : String(err);
logger.warn(
{ err },
'Structural relationship count failed; the graph-write-collapse check will have no ' +
'structural measurement from this run.',
);
}
return { nodes: totalNodes, edges: totalEdges, structuralEdges, structuralEdgesError };
};
/**
* Load cached embeddings from LadybugDB before a rebuild.
* Returns all embedding vectors so they can be re-inserted after the graph is reloaded,
* avoiding expensive re-embedding of unchanged nodes.
*
* Detects old schema (no chunkIndex column) and returns empty cache to trigger rebuild.
*/
export const loadCachedEmbeddings = async (): Promise<{
embeddingNodeIds: Set<string>;View on GitHub (pinned to aac7515d2a)
Solutions
- Re-run the analyze — transient timeouts/locks usually clear and the guard gets its measurement next time.
- Check the structuralEdgesError string on the load result (it names the exact engine message) before assuming data loss.
- Avoid running serve queries against the DB during the load/validation window.
- If it persists, rebuild from scratch (`rm -rf .gitnexus && analyze`) to rule out a corrupt rel table.
Defensive patterns
Strategy: validation
Validate before calling
// After load: branch on the structured result, not the log line
const stats = await getGraphStats(dbPath);
if (stats.structuralEdges === undefined) {
// guard could not measure — do NOT interpret anything about collapse
console.warn('collapse guard unmeasured:', stats.structuralEdgesError);
} Type guard
function hasStructuralMeasurement(s: GraphStats): s is GraphStats & { structuralEdges: number } {
return typeof s.structuralEdges === 'number';
} Prevention
- Always read structuralEdgesError off the result object rather than grepping logs.
- Keep long-running readers off the DB during load so the count query doesn't time out.
- Re-run analyze once before concluding graph corruption from a missing measurement.
When it happens
Trigger: The structural count query inside the validation helper throws: connection trouble, query timeout on a huge rel table, missing/corrupt rel table after a bad load. Only the count degrades — nodes/edges totals may still be returned.
Common situations: Very large indexes where COUNT times out; DB contention with a concurrent serve; a load that half-failed earlier (pairs with the lbug-load warn above); LadybugDB extension faults.
Related errors
- Invalid DuckDB extension name: ${extensionName}
- Invalid DuckDB extension name: ${name}
- Incremental importer BFS: dropped chunk ${chunkIndex} (${bat
- GitNexus query failed (degraded)
- withRetry: maxAttempts must be >= 1, got ${opts.maxAttempts}
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/feca9642c923096b.
Report an issue: GitHub.