abhigyanpatwari/GitNexus · warning

[cobol-copy-expander] Max expansion depth (${maxDepth}) reac

Error message

[cobol-copy-expander] Max expansion depth (${maxDepth}) reached for COPY ${cs.target} in ${srcPath}. Skipping expansion.

What it means

COPY nesting exceeded the maximum expansion depth (DEFAULT_MAX_DEPTH = 10, the expander's maxDepth parameter). COPYs nested deeper than 10 levels are left unexpanded with original lines kept, so the preprocessed output can still contain unresolved COPY statements.

Source

Thrown at gitnexus/src/core/ingestion/cobol/cobol-copy-expander.ts:468

      if (resolvedPath === null) {
        continue;
      }

      // Cycle detection
      if (visited.has(resolvedPath)) {
        if (!warnedCircular.has(resolvedPath)) {
          warnedCircular.add(resolvedPath);
          logger.warn(
            `[cobol-copy-expander] Circular COPY detected: ${cs.target} (${resolvedPath}) ` +
              `includes itself. Skipping expansion.`,
          );
        }
        continue;
      }

      // Max depth exceeded — keep unexpanded
      if (depth >= maxDepth) {
        logger.warn(
          `[cobol-copy-expander] Max expansion depth (${maxDepth}) reached for ` +
            `COPY ${cs.target} in ${srcPath}. Skipping expansion.`,
        );
        continue;
      }

      // Guard against exponential breadth amplification (N copybooks each with N COPYs)
      if (++totalExpansions > MAX_TOTAL_EXPANSIONS) {
        if (!warnedCircular.has('__max_total__')) {
          warnedCircular.add('__max_total__');
          logger.warn(
            `[cobol-copy-expander] Max total expansions (${MAX_TOTAL_EXPANSIONS}) reached ` +
              `in ${srcPath}. Skipping further expansions.`,
          );
        }
        continue;
      }

View on GitHub (pinned to aac7515d2a)

Solutions

  1. Flatten the copybook hierarchy to fewer than 10 nesting levels
  2. When invoking the expander programmatically, pass a higher maxDepth sized to the real chain length
  3. Accept partial expansion and check the preprocessed output for remaining COPY statements

Example fix

// before — default depth
expandCopyStatements(source, { maxDepth: 10 });

// after — chain is 14 levels deep
expandCopyStatements(source, { maxDepth: 20 });
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: measure COPY nesting depth, then size maxDepth to it
function copyChainDepth(source: string, resolve: (t: string) => string | null, seen = new Set<string>()): number {
  const copies = [...source.matchAll(/\bCOPY\s+([\w-]+)/gi)].map((m) => m[1]);
  let max = 0;
  for (const target of copies) {
    if (seen.has(target)) continue; // cycle guard
    const content = resolve(target);
    if (content === null) continue;
    max = Math.max(max, 1 + copyChainDepth(content, resolve, new Set(seen).add(target)));
  }
  return max;
}
const depth = copyChainDepth(mainSource, resolveCopybook);
expandCopyStatements(mainSource, { maxDepth: Math.max(10, depth + 1) });

Type guard

function withinCopyDepth(source: string, resolve: (t: string) => string | null, maxDepth = 10): boolean {
  return copyChainDepth(source, resolve) <= maxDepth;
}

Prevention

When it happens

Trigger: A copybook chain longer than 10 levels deep (C1 COPYs C2, C2 COPYs C3, ... C11), common in layered mainframe include hierarchies.

Common situations: Deeply layered copybook trees built up over decades; hierarchical site-standard includes that fan in at every level.

Related errors


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