{"record":{"id":"e3214569fec59ef9","repo":"mermaid-js/mermaid","slug":"no-nodes-found-in-layout-data","errorCode":null,"errorMessage":"No nodes found in layout data","messagePattern":"No nodes found in layout data","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/mermaid-layout-tidy-tree/src/layout.ts","lineNumber":29,"sourceCode":"} from './types.js';\n\n/**\n * Execute the tidy-tree layout algorithm on generic layout data\n *\n * This function takes layout data and uses the non-layered-tidy-tree-layout\n * algorithm to calculate optimal node positions for tree structures.\n *\n * @param data - The layout data containing nodes, edges, and configuration\n * @param config - Mermaid configuration object\n * @returns Promise resolving to layout result with positioned nodes and edges\n */\nexport function executeTidyTreeLayout(data: LayoutData): Promise<LayoutResult> {\n  let intersectionShift = 50;\n\n  return new Promise((resolve, reject) => {\n    try {\n      if (!data.nodes || !Array.isArray(data.nodes) || data.nodes.length === 0) {\n        throw new Error('No nodes found in layout data');\n      }\n\n      if (!data.edges || !Array.isArray(data.edges)) {\n        data.edges = [];\n      }\n\n      const { leftTree, rightTree, rootNode } = convertToDualTreeFormat(data);\n\n      const gap = 20;\n      const bottomPadding = 40;\n      intersectionShift = 30;\n\n      const bb = new BoundingBox(gap, bottomPadding);\n      const layout = new Layout(bb);\n\n      let leftResult = null;\n      let rightResult = null;\n","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/mermaid-js/mermaid/blob/d93e9c88c01a599c062ee6a3f1462e3558ac6b90/packages/mermaid-layout-tidy-tree/src/layout.ts#L11-L47","documentation":"Thrown by executeTidyTreeLayout when the supplied LayoutData has no usable nodes array (undefined, not an array, or zero-length). The tidy-tree algorithm is built around a node hierarchy, so an empty node set gives it nothing to lay out and it aborts before any geometry work. The check runs inside a Promise executor, so the error is delivered as a rejection rather than a synchronous throw.","triggerScenarios":"Calling executeTidyTreeLayout({nodes:[], edges:[]}); calling it with nodes omitted or set to null; passing a LayoutData object whose nodes were filtered down to nothing upstream.","commonSituations":"An upstream diagram parser produced zero nodes (e.g. an empty mindmap/stateDiagram), a graph extraction step filtered out all nodes by accident, or the layout package is wired in but no real graph data was generated before layout.","solutions":["Ensure data.nodes is a non-empty array before invoking executeTidyTreeLayout.","Trace the upstream producer of LayoutData and confirm it actually emits nodes.","Guard the call site with validateLayoutData(data) plus a length check.","If an empty graph is legitimately possible, short-circuit with an empty LayoutResult instead of calling the layout function."],"exampleFix":"// before\nconst result = await executeTidyTreeLayout(data);\n\n// after\nif (!data.nodes?.length) {\n  return { nodes: [], edges: [] } satisfies LayoutResult;\n}\nconst result = await executeTidyTreeLayout(data);","handlingStrategy":"validation","validationCode":"import { validateLayoutData } from 'mermaid-layout-tidy-tree';\n\nfunction hasNodes(data: unknown): data is { nodes: unknown[] } {\n  return !!data && Array.isArray((data as any).nodes) && (data as any).nodes.length > 0;\n}\n\n// before layout\nvalidateLayoutData(data);\nif (!hasNodes(data)) {\n  throw new Error('Cannot layout: no nodes provided');\n}","typeGuard":"function isLayoutable(data: unknown): data is { nodes: unknown[]; edges: unknown[]; config: unknown } {\n  return !!data\n    && !!(data as any).config\n    && Array.isArray((data as any).nodes) && (data as any).nodes.length > 0\n    && Array.isArray((data as any).edges);\n}","tryCatchPattern":"try {\n  const result = await executeTidyTreeLayout(data);\n} catch (e) {\n  if (e instanceof Error && /No nodes found/.test(e.message)) {\n    // supply empty result or report upstream\n  } else throw e;\n}","preventionTips":["Run validateLayoutData plus a nodes-length check before every layout call.","Centralise LayoutData construction in one factory that always seeds nodes/edges/config.","Assert the producer never returns an empty node array in unit tests."],"tags":["layout","validation","tidy-tree","nodes"],"backgroundTag":null,"analyzedSha":"d93e9c88c01a599c062ee6a3f1462e3558ac6b90","analyzedAt":"2026-08-12T06:23:11.304Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}