{"record":{"id":"71a617298f8d1722","repo":"plotly/plotly.js","slug":"circular-sankey-diagrams-do-not-support-the-input","errorCode":null,"errorMessage":"Circular Sankey diagrams do not support the \"input\" <type>.sort mode; falling back to the default sort.","messagePattern":"Circular Sankey diagrams do not support the \"input\" <type>\\.sort mode; falling back to the default sort\\.","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/traces/sankey/render.js","lineNumber":79,"sourceCode":"        sankey = d3Sankey.sankey();\n    }\n\n    sankey\n      .iterations(c.sankeyIterations)\n      .size(horizontal ? [width, height] : [height, width])\n      .nodeWidth(nodeThickness)\n      .nodePadding(nodePad)\n      .nodeId(function(d) {\n          return d.pointNumber;\n      })\n      .nodeAlign(nodeAlign)\n      .nodes(nodes)\n      .links(links);\n\n    function applyInputSort(type) {\n        if (trace[type].sort === 'input') {\n            if (circular) {\n                Lib.warn(\n                    `Circular Sankey diagrams do not support the \"input\" ${type}.sort mode; falling back to the default sort.`\n                );\n            } else {\n                // Passing null maintains the input order\n                sankey[`${type}Sort`](null);\n            }\n        }\n    }\n    applyInputSort('link');\n    applyInputSort('node');\n\n    var graph = sankey();\n\n    if(sankey.nodePadding() < nodePad) {\n        Lib.warn('node.pad was reduced to ', sankey.nodePadding(), ' to fit within the figure.');\n    }\n\n    // Counters for nested loops","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/plotly/plotly.js/blob/1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314/src/traces/sankey/render.js#L61-L97","documentation":"In src/traces/sankey/render.js:79, applyInputSort detects `node.sort` or `link.sort` set to 'input' while the sankey graph is circular (loops detected). d3-sankey's input-order sorting is incompatible with the circular layout algorithm, so Plotly warns and falls back to the default sort, meaning the rendered order will not preserve the input order.","triggerScenarios":"Setting trace.node.sort: 'input' (or link.sort: 'input') on a sankey trace whose links form a cycle, so `circular` is true in the layout computation.","commonSituations":"Energy/cycle-flow diagrams (money loops, feedback loops) styled with input sort for deterministic ordering; users upgrading plotly.js to a version that added circular sankey support and discovering the sort flag is ignored.","solutions":["Remove the 'input' sort or accept the default sort for circular diagrams.","Break the cycle in your links so the graph is acyclic if input order matters, then keep sort: 'input'.","Reorder the node/link arrays in the data itself, since order can be conveyed without the sort flag."],"exampleFix":"// before\nnode: { sort: 'input' }, links: [ {source:0,target:1}, {source:1,target:0} ]\n// after\nnode: { sort: 'input' }, links: [ {source:0,target:1} ] // cycle removed; or drop sort for circular graphs","handlingStrategy":"validation","validationCode":"function sankeyIsAcyclic(nodes, links) {\n  const idSet = new Set(nodes.map((_, i) => i));\n  const adj = new Map(links.map(l => [l.source, []]));\n  links.forEach(l => adj.get(l.source)?.push(l.target));\n  const state = new Array(nodes.length).fill(0);\n  let cyclic = false;\n  (function dfs(u) {\n    if (state[u] === 1) { cyclic = true; return; }\n    if (state[u] === 2) return;\n    state[u] = 1;\n    (adj.get(u) || []).forEach(dfs);\n    state[u] = 2;\n  })([...idSet][0]);\n  return !cyclic;\n}\n// only set sort: 'input' if sankeyIsAcyclic(nodes, links)","typeGuard":"function supportsInputSort(circular, trace) {\n  return !circular && (trace.node.sort === 'input' || trace.link.sort === 'input');\n}","tryCatchPattern":null,"preventionTips":["Detect cycles in your link data before requesting sort: 'input'.","Do not rely on 'input' sort for circular sankey diagrams; encode order in array order instead.","Check the plotly.js changelog when enabling circular sankey features."],"tags":["sankey","cyclic-graph","sorting","fallback"],"backgroundTag":"unsupported-option-fallback","analyzedSha":"1d090e0b5ffb8d0fdf6e0e4ff51d3f3cf67f1314","analyzedAt":"2026-09-02T22:03:39.906Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}