mastra-ai/mastra · error · Error

SankeyChart must be used within Sankey

Error message

SankeyChart must be used within Sankey

What it means

useSankeyRenderContext reads SankeyRenderContext, which supplies the computed graph, enabledColumns, hueMap, and fixed-geometry flags used to render the diagram. The context defaults to null and is only populated by <Sankey>, so calling this hook outside a Sankey render tree throws this error. Unlike useSankey (controls), this hook exposes internal render geometry and is only meaningful within the chart.

Source

Thrown at packages/playground-ui/src/ds/components/SankeyChart/sankey-context.tsx:131

      >
        {children}
      </SankeyRenderContext.Provider>
    </SankeyControlsContext.Provider>
  );
}

// Context providers and their hooks intentionally share this module.
// eslint-disable-next-line react-refresh/only-export-components
export function useSankey() {
  const context = useContext(SankeyControlsContext);
  if (!context) throw new Error('useSankey must be used within Sankey');
  return context;
}

// eslint-disable-next-line react-refresh/only-export-components
export function useSankeyRenderContext() {
  const context = useContext(SankeyRenderContext);
  if (!context) throw new Error('SankeyChart must be used within Sankey');
  return context;
}

function orderColumns(columns: Array<SankeyChartColumn>, order: Array<string>) {
  const positions = new Map(order.map((id, index) => [id, index]));
  return [...columns].sort(
    (left, right) => (positions.get(left.id) ?? columns.length) - (positions.get(right.id) ?? columns.length),
  );
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Ensure the consumer is rendered inside the <Sankey> component tree (e.g., via its render props/children API).
  2. Pass graph/columns/hueMap explicitly via props if the component must live outside the chart.
  3. Wrap isolated stories or tests with <Sankey> before rendering consumers of this hook.
  4. Fix conditional rendering so the Sankey provider never unmounts while render-dependent children remain mounted.

Example fix

// before
<Sankey data={data} />
<CustomNodeLabel /> {/* useSankeyRenderContext() throws */}

// after
<Sankey data={data}>
  <CustomNodeLabel />
</Sankey>
Defensive patterns

Strategy: validation

Validate before calling

const render = useContext(SankeyRenderContext);
if (!render) {
  // not inside <Sankey>: render placeholder instead of using graph/hueMap
}

Type guard

const hasRenderContext = (v: SankeyRenderContextValue | null): v is SankeyRenderContextValue => v != null;

Try / catch

try {
  const render = useSankeyRenderContext();
  drawOverlay(render.graph, render.hueMap);
} catch {
  // outside <Sankey>: skip overlay
}

Prevention

When it happens

Trigger: Invoking useSankeyRenderContext() from a custom node/link renderer, tooltip, or overlay mounted outside <Sankey>; using it in a story/test that renders components in isolation; calling it in a component that renders before Sankey mounts its render context.

Common situations: Building custom SVG overlays over the sankey diagram and placing them as siblings rather than children; extracting the chart's tooltip into a separate route; snapshot tests rendering a node component without the chart wrapper.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/6324e30dd9c2ca9b. Report an issue: GitHub.