{"record":{"id":"3c10ac35b87f646c","repo":"vercel/next.js","slug":"source-at-index-sourceindex-not-found","errorCode":null,"errorMessage":"Source at index ${sourceIndex} not found","messagePattern":"Source at index (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/bundle-analyzer/lib/treemap-layout.ts","lineNumber":119,"sourceCode":"  for (const rootIdx of roots) {\n    processDirectory(rootIdx)\n  }\n\n  return metadata\n}\n\n// Internal function that uses precomputed metadata\nfunction computeTreemapLayoutFromAnalyzeInternal(\n  analyzeData: AnalyzeData,\n  sourceIndex: SourceIndex,\n  foldedPath: string,\n  rect: LayoutRect,\n  metadata: SourceMetadata[],\n  sizeMode: SizeMode\n): LayoutNode {\n  const source = analyzeData.source(sourceIndex)\n  if (!source) {\n    throw new Error(`Source at index ${sourceIndex} not found`)\n  }\n\n  const isDirectory = source.path.endsWith('/') || !source.path\n\n  const childrenIndices = analyzeData.sourceChildren(sourceIndex)\n\n  // Fold single-child directories\n  if (\n    childrenIndices.length === 1 &&\n    isDirectory &&\n    (foldedPath + source.path).length <= 40\n  ) {\n    const childIndex = childrenIndices[0]\n    const child = analyzeData.source(childIndex)\n    if (child?.path.endsWith('/')) {\n      return computeTreemapLayoutFromAnalyzeInternal(\n        analyzeData,\n        childIndex,","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/vercel/next.js/blob/0ae8c72462952df163f1b1e0726641bc5b40dc93/apps/bundle-analyzer/lib/treemap-layout.ts#L101-L137","documentation":"Thrown by computeTreemapLayoutFromAnalyzeInternal when analyzeData.source(sourceIndex) returns undefined, meaning the source index is out of bounds for the analyze header's sources array (analyze-data.ts:240 just does sources[index]). It is an internal-consistency error: the treemap traversal (either the root index passed to computeTreemapLayoutFromAnalyze or a child index returned by sourceChildren) referenced a source that does not exist in the loaded analyze data. In a well-formed analyze report this never happens, so hitting it indicates a corrupt/mismatched @next/analyze report or an out-of-band index computed elsewhere.","triggerScenarios":"Calling computeTreemapLayoutFromAnalyze (treemap-layout.ts:271) with a sourceIndex >= analyzeData.sourceCount(), or a child index returned by analyzeData.sourceChildren(idx) that points past the end of the sources array. Also reachable via the single-child directory fold at lines 127-144 and the recursive children walk at 247-256 when the analyze header's tree links are inconsistent with its sources list.","commonSituations":"Loading an analyze report produced by a different/older @next/build-analyzer or webpack-bundle-analyzer plugin version whose tree format differs; manually constructing or hand-editing an AnalyzeData instance and passing a stale sourceIndex; a partial/truncated report JSON where the sources array was cut off but child references remained.","solutions":["Regenerate the analyze report with the matching bundle-analyzer version (re-run the build's analyze step) so the tree structure and sources list agree.","Before computing the layout, guard the requested sourceIndex against analyzeData.sourceCount() and the children indices against the same bound; surface a clearer error about which index is stale.","If consuming reports from multiple sources, validate the analyze header once on load (sources length, every child index < sources.length) instead of letting the layout crash deep in recursion.","If you built AnalyzeData by hand, audit the code that fills analyzeHeader.sources and the parent->child index maps for off-by-one or stale-reference bugs."],"exampleFix":"// before\nconst root = computeTreemapLayoutFromAnalyze(analyzeData, requestedIndex, rect, filter, sizeMode)\n\n// after\nif (requestedIndex < 0 || requestedIndex >= analyzeData.sourceCount()) {\n  throw new Error(\n    `sourceIndex ${requestedIndex} out of range [0, ${analyzeData.sourceCount()})`\n  )\n}\nconst root = computeTreemapLayoutFromAnalyze(analyzeData, requestedIndex, rect, filter, sizeMode)","handlingStrategy":"validation","validationCode":"function isValidSourceIndex(analyzeData: AnalyzeData, idx: number): boolean {\n  return Number.isInteger(idx) && idx >= 0 && idx < analyzeData.sourceCount()\n}\n\n// before computing any layout:\nconst roots = analyzeData.sourceRoots()\nfor (const r of roots) {\n  if (!isValidSourceIndex(analyzeData, r)) throw new Error(`stale root index ${r}`)\n  for (const c of analyzeData.sourceChildren(r)) {\n    if (!isValidSourceIndex(analyzeData, c)) throw new Error(`stale child ${c} of root ${r}`)\n  }\n}","typeGuard":"function isAnalyzable(data: AnalyzeData, idx: number): data is AnalyzeData & { sourceIndex: number } {\n  return data.source(idx) !== undefined\n}","tryCatchPattern":"try {\n  return computeTreemapLayoutFromAnalyze(analyzeData, sourceIndex, rect, filter, sizeMode)\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Source at index')) {\n    // regenerate the report rather than render a half-broken treemap\n    throw new Error('Analyze report is inconsistent — regenerate it with the matching analyzer version', { cause: err })\n  }\n  throw err\n}","preventionTips":["Always produce and consume analyze reports with the same bundle-analyzer / webpack-bundle-analyzer version.","Validate the analyze header once on load: sources length > 0 and every child/root index in bounds.","Don't reuse a sourceIndex across reloads of the report — re-resolve via getSourceIndexFromPath.","Treat this error as a data-integrity bug, not a user input error; never silently swallow it."],"tags":["treemap","data-integrity","index-out-of-bounds","bundle-analyzer"],"analyzedSha":"0ae8c72462952df163f1b1e0726641bc5b40dc93","analyzedAt":"2026-08-06T19:44:29.143Z","schemaVersion":2},"datasetVersion":"2026-08-07T02:17:10.218Z"}