{"record":{"id":"439f583939401bee","repo":"aaif-goose/goose","slug":"sankey-data-must-include-at-least-one-node-and-one","errorCode":null,"errorMessage":"Sankey data must include at least one node and one link.","messagePattern":"Sankey data must include at least one node and one link\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/goose-mcp/src/autovisualisation/templates/sankey_template.html","lineNumber":225,"sourceCode":null,"sourceCodeStart":null,"sourceCodeEnd":null,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose-mcp/src/autovisualisation/templates/sankey_template.html#L225","documentation":"Client-side guard inside the D3 sankey HTML template rendered by the autovisualiser MCP tool: renderData() requires data.nodes and data.links to be non-empty arrays before calling drawSankey, because d3-sankey throws cryptic errors on empty graphs. The thrown error is immediately caught and displayed in the SVG as 'Unable to render diagram: ...', so it degrades to an inline message rather than crashing the webview.","triggerScenarios":"The model/autovisualiser tool sends a Sankey spec with nodes: [] or links: [] (e.g. the underlying data summarized to nothing, or all edges were filtered out); a dataset with only isolated nodes and no links; malformed payload where nodes/links keys exist but are empty arrays.","commonSituations":"LLM generating a chart from a table whose flows all collapsed to zero; user asking for a flow diagram of data with a single category (no links possible); upstream aggregation bugs producing empty edge lists.","solutions":["Ensure the Sankey payload has at least one node AND one link (source+target pair) before rendering","If the data genuinely has no flows, pick a different chart type (bar/table) instead of a sankey","Filter/aggregate upstream so trivial flows still produce one link rather than an empty set","If you are the tool author: validate nodes/links length in the Rust handler before sending data to the template"],"exampleFix":"// before\nrenderData({ nodes: [{ name: 'A' }], links: [] }); // throws inside template\n// after\nrenderData({\n  nodes: [{ name: 'A' }, { name: 'B' }],\n  links: [{ source: 0, target: 1, value: 10 }],\n});","handlingStrategy":"validation","validationCode":"// (template-side, before McpAppBridge onData -> renderData)\nfunction isRenderableSankey(data) {\n  return Boolean(\n    data && Array.isArray(data.nodes) && data.nodes.length > 0 &&\n    Array.isArray(data.links) && data.links.length > 0\n  );\n}","typeGuard":"const isNonEmptySankey = (d: unknown): d is { nodes: unknown[]; links: unknown[] } =>\n  typeof d === 'object' && d !== null &&\n  Array.isArray((d as any).nodes) && (d as any).nodes.length > 0 &&\n  Array.isArray((d as any).links) && (d as any).links.length > 0;","tryCatchPattern":"// Already handled internally: renderData catches and draws\n// 'Unable to render diagram: <message>'. Callers should validate data shape\n// upstream so users never see the fallback text.","preventionTips":["Validate nodes.length && links.length in the Rust tool before emitting the HTML payload","Prefer bar/table charts for datasets that aggregate to zero flows","Include a sample valid payload in tool docs so agents learn the shape"],"tags":["d3","sankey","visualization","validation","javascript"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}