abhigyanpatwari/GitNexus · warning
C++ capture extraction exceeded its ${budgetMs}ms budget for
Error message
C++ capture extraction exceeded its ${budgetMs}ms budget for ${filePath}; returning partial captures for this file (#2432). What it means
Per-file wall-clock deadline for C++ tree-sitter capture extraction (default 20,000 ms via GITNEXUS_CPP_CAPTURE_BUDGET_MS; checked every 64 matches to bound drift). When the extraction loop blows the deadline — typically one pathological file with an enormous match count — it stops and returns partial captures for that file only (#2432), degrading symbol/relationship data for it.
Source
Thrown at gitnexus/src/core/ingestion/languages/cpp/captures.ts:196
// per file, 151s on a 194KB file that parses in 46ms. The index makes each
// lookup O(1) after a single lazily-built pass.
resetCppFileLookupIndex();
// Track ranges where typedef-struct/enum was captured as its concrete type
// so we can suppress the duplicate @declaration.typedef match.
const concreteTypedefRanges = new Set<string>();
// #2432: per-file deadline for the loop below (see cppCaptureBudgetMs).
// Checked every 64 matches — post-index a single iteration is microseconds,
// so the check granularity costs nothing and bounds the drift past the
// deadline to well under a second.
const budgetMs = cppCaptureBudgetMs();
const deadline = Date.now() + budgetMs;
let matchIndex = 0;
for (const m of rawMatches) {
if ((matchIndex++ & 63) === 0 && Date.now() >= deadline) {
logger.warn(
{ filePath, budgetMs, processedMatches: matchIndex - 1, totalMatches: rawMatches.length },
`C++ capture extraction exceeded its ${budgetMs}ms budget for ${filePath}; returning partial captures for this file (#2432).`,
);
break;
}
const grouped: Record<string, Capture> = {};
// Parallel tag -> captured SyntaxNode map. The tree-sitter query already
// hands us each matched node as `c.node`, so anchors resolve via a
// type-guarded lookup (`nodeIfType`) instead of re-deriving them with
// `findNodeAtRange(tree.rootNode, ...)` per match — the
// O(matches × rootChildren) root-walk fixed for go #1848 / python #1918 /
// rust/csharp #1915 / java, mirrored here for C++ (#1951). Each C++
// scope-query anchor used below captures directly ON the node the old
// root-walk re-derived (verified against CPP_SCOPE_QUERY in query.ts and a
// real-parse AST probe), so the type check is exact.
const nodeMap: Record<string, SyntaxNode> = {};
for (const c of m.captures) {
const tag = '@' + c.name;View on GitHub (pinned to aac7515d2a)
Solutions
- Raise the budget: export GITNEXUS_CPP_CAPTURE_BUDGET_MS=60000
- Split the pathological file or exclude it via ignore rules if it is generated
- Re-run analyze on a less loaded machine — load-induced overruns often clear
Example fix
# before — default 20s budget; huge generated.h times out # after export GITNEXUS_CPP_CAPTURE_BUDGET_MS=60000 node .gitnexus/run.cjs analyze --index-only
Defensive patterns
Strategy: retry
Validate before calling
import { statSync } from 'node:fs';
// Pre-check the usual driver: one enormous generated C++ header
const budgetMs = parseInt(process.env.GITNEXUS_CPP_CAPTURE_BUDGET_MS ?? '20000', 10);
const bigHeaders = cppFiles.filter((f) => statSync(f).size > 2 * 1024 * 1024);
if (bigHeaders.length > 0 && budgetMs <= 20_000) {
console.warn('large C++ files present with a tight capture budget:', bigHeaders);
// raise GITNEXUS_CPP_CAPTURE_BUDGET_MS or split/exclude before analyze
} Type guard
function captureBudgetLikelySufficient(fileSizeBytes: number, budgetMs = 20000): boolean {
// rough heuristic: ~100us per 1KB of dense generated header under normal load
return fileSizeBytes / 1024 * 0.1 <= budgetMs;
} Prevention
- Set GITNEXUS_CPP_CAPTURE_BUDGET_MS higher (e.g. 60000) on machines that index giant generated headers
- Split or exclude generated protobuf/UI headers that dwarf hand-written sources
- Re-run analyze on a less loaded machine when the warning looks load-induced; partial captures only affect the named file
When it happens
Trigger: A single very large or dense C++ file (generated protobuf/UI headers, huge template-heavy sources) whose rawMatches exceed the budget; the env var set lower than needed; or a heavily loaded machine inflating wall-clock time.
Common situations: Indexing generated headers; CI runners under parallel load; symptom is incomplete C++ symbols or call edges for exactly one file while the rest of the index is fine.
Related errors
- cpp range-binding: parse timed out, skipping file
- [cfg] unresolved goto label "${label}" routed to EXIT (${fro
- [cobol-processor] Skipping oversized file (${(file.content.l
- [gitnexus serve] Ignoring ${PUBLIC_ORIGIN_ENV}=${raw} — not
- [gitnexus serve] Ignoring ${TRUST_PROXY_ENV}=${value} (${rea
AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20).
Data as JSON: /api/errors/a1166c3d1935ae53.
Report an issue: GitHub.