{"record":{"id":"4296ed529ddfa911","repo":"mastra-ai/mastra","slug":"usesankey-must-be-used-within-sankey","errorCode":null,"errorMessage":"useSankey must be used within Sankey","messagePattern":"useSankey must be used within Sankey","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/playground-ui/src/ds/components/SankeyChart/sankey-context.tsx","lineNumber":124,"sourceCode":"\n  const controlColumns = orderedColumns.map(column => ({ ...column, visible: visibleIds.has(column.id) }));\n\n  return (\n    <SankeyControlsContext.Provider value={{ columns: controlColumns, toggleColumn, reorderColumns }}>\n      <SankeyRenderContext.Provider\n        value={{ graph, enabledColumns, hueMap, usesFixedGeometry: getRecordLayoutWeight !== undefined }}\n      >\n        {children}\n      </SankeyRenderContext.Provider>\n    </SankeyControlsContext.Provider>\n  );\n}\n\n// Context providers and their hooks intentionally share this module.\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useSankey() {\n  const context = useContext(SankeyControlsContext);\n  if (!context) throw new Error('useSankey must be used within Sankey');\n  return context;\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useSankeyRenderContext() {\n  const context = useContext(SankeyRenderContext);\n  if (!context) throw new Error('SankeyChart must be used within Sankey');\n  return context;\n}\n\nfunction orderColumns(columns: Array<SankeyChartColumn>, order: Array<string>) {\n  const positions = new Map(order.map((id, index) => [id, index]));\n  return [...columns].sort(\n    (left, right) => (positions.get(left.id) ?? columns.length) - (positions.get(right.id) ?? columns.length),\n  );\n}\n","sourceCodeStart":106,"sourceCodeEnd":141,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/playground-ui/src/ds/components/SankeyChart/sankey-context.tsx#L106-L141","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n<div className=\"layout\">\n  <SankeyControls /> {/* calls useSankey() — throws */}\n  <Sankey data={data} />\n</div>\n\n// after\n<div className=\"layout\">\n  <Sankey data={data}>\n    <SankeyControls />\n  </Sankey>\n</div>","handlingStrategy":"validation","validationCode":"const context = useContext(SankeyControlsContext);\nif (!context) {\n  // render controls disabled or skip rendering instead of calling useSankey-dependent paths\n}","typeGuard":"const hasSankeyControls = (v: ReturnType<typeof useSankey> | null): v is NonNullable<ReturnType<typeof useSankey>> => v != null;","tryCatchPattern":"try {\n  const controls = useSankey();\n  controls.toggleColumn(id);\n} catch {\n  // outside <Sankey>: render static fallback\n}","preventionTips":["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."],"tags":["react","context","provider-missing","charts"],"backgroundTag":"missing-react-context-provider","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}