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

  1. Raise the budget: export GITNEXUS_CPP_CAPTURE_BUDGET_MS=60000
  2. Split the pathological file or exclude it via ignore rules if it is generated
  3. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@aac7515d2a (2026-08-20). Data as JSON: /api/errors/a1166c3d1935ae53. Report an issue: GitHub.