plotly/plotly.js · warning

Circular Sankey diagrams do not support the "input" <type>.s

Error message

Circular Sankey diagrams do not support the "input" <type>.sort mode; falling back to the default sort.

What it means

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.

Source

Thrown at src/traces/sankey/render.js:79

        sankey = d3Sankey.sankey();
    }

    sankey
      .iterations(c.sankeyIterations)
      .size(horizontal ? [width, height] : [height, width])
      .nodeWidth(nodeThickness)
      .nodePadding(nodePad)
      .nodeId(function(d) {
          return d.pointNumber;
      })
      .nodeAlign(nodeAlign)
      .nodes(nodes)
      .links(links);

    function applyInputSort(type) {
        if (trace[type].sort === 'input') {
            if (circular) {
                Lib.warn(
                    `Circular Sankey diagrams do not support the "input" ${type}.sort mode; falling back to the default sort.`
                );
            } else {
                // Passing null maintains the input order
                sankey[`${type}Sort`](null);
            }
        }
    }
    applyInputSort('link');
    applyInputSort('node');

    var graph = sankey();

    if(sankey.nodePadding() < nodePad) {
        Lib.warn('node.pad was reduced to ', sankey.nodePadding(), ' to fit within the figure.');
    }

    // Counters for nested loops

View on GitHub (pinned to 1d090e0b5f)

Solutions

  1. Remove the 'input' sort or accept the default sort for circular diagrams.
  2. Break the cycle in your links so the graph is acyclic if input order matters, then keep sort: 'input'.
  3. Reorder the node/link arrays in the data itself, since order can be conveyed without the sort flag.

Example fix

// before
node: { sort: 'input' }, links: [ {source:0,target:1}, {source:1,target:0} ]
// after
node: { sort: 'input' }, links: [ {source:0,target:1} ] // cycle removed; or drop sort for circular graphs
Defensive patterns

Strategy: validation

Validate before calling

function sankeyIsAcyclic(nodes, links) {
  const idSet = new Set(nodes.map((_, i) => i));
  const adj = new Map(links.map(l => [l.source, []]));
  links.forEach(l => adj.get(l.source)?.push(l.target));
  const state = new Array(nodes.length).fill(0);
  let cyclic = false;
  (function dfs(u) {
    if (state[u] === 1) { cyclic = true; return; }
    if (state[u] === 2) return;
    state[u] = 1;
    (adj.get(u) || []).forEach(dfs);
    state[u] = 2;
  })([...idSet][0]);
  return !cyclic;
}
// only set sort: 'input' if sankeyIsAcyclic(nodes, links)

Type guard

function supportsInputSort(circular, trace) {
  return !circular && (trace.node.sort === 'input' || trace.link.sort === 'input');
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of plotly/plotly.js@1d090e0b5f (2026-09-02). Data as JSON: /api/errors/71a617298f8d1722. Report an issue: GitHub.