{"record":{"id":"853f9f904e8fb0d4","repo":"abhigyanpatwari/GitNexus","slug":"cobol-copy-expander-max-total-expansions-max","errorCode":null,"errorMessage":"[cobol-copy-expander] Max total expansions (${MAX_TOTAL_EXPANSIONS}) reached in ${srcPath}. Skipping further expansions.","messagePattern":"\\[cobol-copy-expander\\] Max total expansions \\((.+?)\\) reached in (.+?)\\. Skipping further expansions\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"gitnexus/src/core/ingestion/cobol/cobol-copy-expander.ts","lineNumber":479,"sourceCode":"          );\n        }\n        continue;\n      }\n\n      // Max depth exceeded — keep unexpanded\n      if (depth >= maxDepth) {\n        logger.warn(\n          `[cobol-copy-expander] Max expansion depth (${maxDepth}) reached for ` +\n            `COPY ${cs.target} in ${srcPath}. Skipping expansion.`,\n        );\n        continue;\n      }\n\n      // Guard against exponential breadth amplification (N copybooks each with N COPYs)\n      if (++totalExpansions > MAX_TOTAL_EXPANSIONS) {\n        if (!warnedCircular.has('__max_total__')) {\n          warnedCircular.add('__max_total__');\n          logger.warn(\n            `[cobol-copy-expander] Max total expansions (${MAX_TOTAL_EXPANSIONS}) reached ` +\n              `in ${srcPath}. Skipping further expansions.`,\n          );\n        }\n        continue;\n      }\n\n      // Read the copybook content\n      const copybookContent = readFile(resolvedPath);\n      if (copybookContent === null) {\n        continue;\n      }\n\n      // Apply REPLACING transformations\n      const replaced = applyReplacing(copybookContent, cs.replacing);\n\n      // Recurse into the copybook for nested COPYs\n      const nestedVisited = new Set(visited);","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/aac7515d2a8c50a1f8f923c6fb77218b333560d6/gitnexus/src/core/ingestion/cobol/cobol-copy-expander.ts#L461-L497","documentation":"The copybook expander counts cumulative COPY expansions per file; once the count passes MAX_TOTAL_EXPANSIONS (500) it stops expanding further COPYs, leaving them unexpanded, and warns once (warnedCircular gate keyed '__max_total__'). This bounds exponential breadth amplification: N copybooks each containing N COPYs.","triggerScenarios":"A file whose copybooks fan out — many COPY statements where each expanded copybook itself contains many more COPYs — pushing cumulative expansions past 500 even though nesting depth stays under 10.","commonSituations":"Heavily reused copybook libraries referenced dozens of times per program; generated COBOL that repeats COPY boilerplate; members assembled from shared fragment libraries.","solutions":["Reduce copybook reuse breadth — deduplicate repeated COPY statements of the same member","Split the oversized program into smaller members","Accept partial expansion and audit remaining COPY statements in the preprocessed output"],"exampleFix":"* before — 60 copies of a 10-COPY fragment (600 total expansions)\n       COPY FRAG. COPY FRAG. ... (x60)\n\n* after — reference one expanded copy or reduce fan-out below 500 total","handlingStrategy":"validation","validationCode":"// Pre-flight: estimate total expansions (fan-out sum per level) before running\nfunction estimateExpansions(source: string, resolve: (t: string) => string | null, depth = 0): number {\n  if (depth >= 10) return 0;\n  let total = 0;\n  for (const m of source.matchAll(/\\bCOPY\\s+([\\w-]+)/gi)) {\n    const content = resolve(m[1]);\n    total += 1 + (content ? estimateExpansions(content, resolve, depth + 1) : 0);\n  }\n  return total;\n}\nif (estimateExpansions(src, resolveCopybook) > 500) {\n  console.warn('COPY fan-out exceeds the 500-expansion budget — reduce reuse or split the member');\n}","typeGuard":"function withinExpansionBudget(source: string, resolve: (t: string) => string | null, budget = 500): boolean {\n  return estimateExpansions(source, resolve) <= budget;\n}","tryCatchPattern":null,"preventionTips":["Avoid pasting the same COPY fragment dozens of times into one member — deduplicate","Split programs whose copybook fan-out is huge into smaller members","Remember the 500-expansion guard is per file: reuse multiplies across every COPY site"],"tags":["cobol","copybook","expansion-budget","preprocessor"],"backgroundTag":"include-expansion-limit","analyzedSha":"aac7515d2a8c50a1f8f923c6fb77218b333560d6","analyzedAt":"2026-08-20T23:29:22.980Z","contentChangedAt":"2026-08-20T23:29:22.980Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}