mermaid-js/mermaid · error · Error

Layout data is required

Error message

Layout data is required

What it means

First guard in validateLayoutData, thrown when executeCoseBilkentLayout receives a falsy `data` argument (null/undefined). validateLayoutData runs at the top of the cose-bilkent layout (layout.ts:29) before any cytoscape work, so this indicates the caller passed no layout payload at all. Subsequent guards (108–111) check inner fields; this one catches total absence.

Source

Thrown at packages/mermaid/src/rendering-util/layout-algorithms/cose-bilkent/layout.ts:57

    return {
      nodes: positionedNodes,
      edges: positionedEdges,
    };
  } catch (error) {
    log.error('Error in cose-bilkent layout algorithm:', error);
    throw error;
  }
}

/**
 * Validate layout data structure
 * @param data - The data to validate
 * @returns True if data is valid, throws error otherwise
 */
export function validateLayoutData(data: LayoutData): boolean {
  if (!data) {
    throw new Error('Layout data is required');
  }

  if (!data.config) {
    throw new Error('Configuration is required in layout data');
  }

  if (!data.rootNode) {
    throw new Error('Root node is required');
  }

  if (!data.nodes || !Array.isArray(data.nodes)) {
    throw new Error('No nodes found in layout data');
  }

  if (!Array.isArray(data.edges)) {
    throw new Error('Edges array is required in layout data');
  }

View on GitHub (pinned to d93e9c88c0)

Solutions

  1. Ensure the LayoutData passed to executeCoseBilkentLayout / render is a fully constructed object, not null/undefined.
  2. Inspect the upstream parser/diagram-db step that builds LayoutData — if it returned null, fix or short-circuit before layout.
  3. Add a guard at the call site: if (!data) return; to skip layout for empty diagrams.
  4. Reproduce with logging just before the layout call to see why data is falsy.

Example fix

// before
await executeCoseBilkentLayout(maybeData, config); // maybeData may be undefined
// after
if (!maybeData) throw new Error('parser produced no layout data');
await executeCoseBilkentLayout(maybeData, config);
Defensive patterns

Strategy: validation

Validate before calling

function hasLayoutData(data: unknown): data is object {
  return data !== null && data !== undefined;
}
if (!hasLayoutData(data)) throw new Error('no layout data produced upstream');

Type guard

function isLayoutData(x: unknown): x is { config: unknown; rootNode: unknown; nodes: unknown[]; edges: unknown[] } {
  return !!x && typeof x === 'object' && 'config' in x && 'rootNode' in x && Array.isArray((x as any).nodes) && Array.isArray((x as any).edges);
}

Try / catch

try { validateLayoutData(data); } catch (e) { if (/Layout data is required/.test(String(e))) return; throw e; }

Prevention

When it happens

Trigger: Calling executeCoseBilkentLayout(undefined, config) or render of a LayoutData built from a diagram that produced no parse result (e.g. an empty/malformed graph that yielded null before reaching layout). Any path where the LayoutData object is null/undefined reaches this throw.

Common situations: A diagram type whose parser returned null/undefined being routed to the cose-bilkent layout, an integration that constructs LayoutData conditionally and skips the assignment, or a refactor that dropped the data argument. Mostly an internal-contract violation rather than an end-user config error.

Related errors


AI-assisted analysis of mermaid-js/mermaid@d93e9c88c0 (2026-08-12). Data as JSON: /api/errors/5e8008db2283feb8. Report an issue: GitHub.