mastra-ai/mastra · error · Error
useSankey must be used within Sankey
Error message
useSankey must be used within Sankey
What it means
useSankey reads SankeyControlsContext, which the <Sankey> component populates with control columns, toggleColumn, and reorderColumns. When the hook runs with no provider above it, the context is null and this error is thrown. The Sankey design-system component intentionally shares its context and hooks in one module, so importing the hook is easy but using it outside <Sankey> is invalid.
Source
Thrown at packages/playground-ui/src/ds/components/SankeyChart/sankey-context.tsx:124
const controlColumns = orderedColumns.map(column => ({ ...column, visible: visibleIds.has(column.id) }));
return (
<SankeyControlsContext.Provider value={{ columns: controlColumns, toggleColumn, reorderColumns }}>
<SankeyRenderContext.Provider
value={{ graph, enabledColumns, hueMap, usesFixedGeometry: getRecordLayoutWeight !== undefined }}
>
{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
- Render the component calling useSankey as a descendant of <Sankey>.
- Move external controls into the Sankey subtree, or lift the state they need out of the context and pass it via props.
- Guard rendering so controls only mount when the Sankey provider is present (e.g., render both together from one parent).
- If a portal is used, place the portal inside the Sankey React subtree so context propagates.
Example fix
// before
<div className="layout">
<SankeyControls /> {/* calls useSankey() — throws */}
<Sankey data={data} />
</div>
// after
<div className="layout">
<Sankey data={data}>
<SankeyControls />
</Sankey>
</div> Defensive patterns
Strategy: validation
Validate before calling
const context = useContext(SankeyControlsContext);
if (!context) {
// render controls disabled or skip rendering instead of calling useSankey-dependent paths
} Type guard
const hasSankeyControls = (v: ReturnType<typeof useSankey> | null): v is NonNullable<ReturnType<typeof useSankey>> => v != null;
Try / catch
try {
const controls = useSankey();
controls.toggleColumn(id);
} catch {
// outside <Sankey>: render static fallback
} Prevention
- Keep sankey controls inside the <Sankey> children/render API.
- Do not split control panels into sibling trees that need chart context.
- Compose stories and tests with the full <Sankey> wrapper.
- If state must be shared externally, lift it out of the context into props/state.
When it happens
Trigger: Calling useSankey() in a custom legend/controls component rendered outside the <Sankey> tree; rendering InvalidControls-like controls in a parent layout that sits above <Sankey>; conditionally mounting <Sankey> while its control sidebar still renders.
Common situations: Repositioning sankey column controls into a separate panel outside the chart; building a storybook story that renders only the controls; refactoring the chart so the provider unmounts before dependent controls.
Related errors
- SankeyChart must be used within Sankey
- ${hookName} must be used within MessageScrollerProvider.
- Plan compound components must be rendered inside <Plan>.
- ToolCall compounds must be rendered within ToolCall
- Comment compounds must be rendered within Comment
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/4296ed529ddfa911.
Report an issue: GitHub.