abhigyanpatwari/GitNexus · warning · ParseTimeoutError

cpp range-binding: parse timed out, skipping file

Error message

cpp range-binding: parse timed out, skipping file

What it means

The C++ range-binding pass re-parses each file with parseSourceSafe (reusing a cached tree when available). parseSourceSafe arms a per-parse wall-clock budget — 15 s by default, overridable via GITNEXUS_PARSE_TIMEOUT_MS, 0 disables — and throws ParseTimeoutError when a pathological input exceeds it. The pass catches ParseTimeoutError specifically, warns 'cpp range-binding: parse timed out, skipping file', and skips only that file's range bindings; every other error rethrows.

Source

Thrown at gitnexus/src/core/ingestion/languages/cpp/range-bindings.ts:47

  for (const parsed of parsedFiles) {
    const sourceText = ctx.fileContents.get(parsed.filePath);
    if (sourceText === undefined) continue;

    const cachedTree = ctx.treeCache?.get(parsed.filePath) as
      | ReturnType<typeof parser.parse>
      | undefined;
    let tree: ReturnType<typeof parser.parse>;
    if (cachedTree !== undefined) {
      tree = cachedTree;
    } else {
      try {
        tree = parseSourceSafe(parser, sourceText, undefined, {
          bufferSize: getTreeSitterBufferSize(sourceText),
        });
      } catch (err) {
        if (err instanceof ParseTimeoutError) {
          logger.warn(
            { file: parsed.filePath },
            'cpp range-binding: parse timed out, skipping file',
          );
          continue;
        }
        throw err;
      }
    }

    const moduleScope = parsed.scopes.find((s) => s.kind === 'Module');
    if (moduleScope === undefined) continue;

    const scopeMap = new Map(parsed.scopes.map((s) => [s.id, s]));

    // Build a map from parameter name → AST parameter_declaration node
    // so we can extract the un-normalized template type from the AST.
    const paramTypeMap = buildParamTemplateMap(tree.rootNode);

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Identify the file from the warn's { file } field
  2. Exclude that file from indexing or split the monster header — it is pathological by any measure
  3. Raise the budget: GITNEXUS_PARSE_TIMEOUT_MS=25000 (keep it below the worker pool's 30 s idle timeout, as the safe-parse comment requires)
  4. Run analyze on a less loaded machine so the same file parses within budget
  5. Accept the skip — only range bindings for that file are missing; scopes still resolve

Example fix

# before: default 15s per-parse budget trips on huge generated headers
npx gitnexus analyze

# after: raise the budget below the 30s worker idle ceiling
GITNEXUS_PARSE_TIMEOUT_MS=25000 npx gitnexus analyze
Defensive patterns

Strategy: validation

Validate before calling

// prescreen before indexing: skip monolithic generated headers
const MAX_BYTES = 1_500_000; // tune to your hardware
if ((await fs.promises.stat(file)).size > MAX_BYTES) addToFileExclusions(file);

Try / catch

try {
  tree = parseSourceSafe(parser, sourceText, undefined, { bufferSize: getTreeSitterBufferSize(sourceText) });
} catch (err) {
  if (err instanceof ParseTimeoutError) { skipRangeBindingsFor(file); return; }
  throw err; // non-timeout parse failures are real errors
}

Prevention

When it happens

Trigger: A C/C++ source or header whose tree-sitter parse exceeds the budget on the available CPU: enormous generated headers, deeply nested template-heavy code, minified bundles, or a heavily loaded/throttled machine making even moderate files exceed 15 s.

Common situations: Indexing third_party/vendored code with 10k-line generated headers; CI runners with throttled CPU where parse times balloon; running analyze alongside a full build so workers are starved.

Understand the failure class

Related errors


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