iced-rs/iced · error

Node configuration and split count do not match

Error message

Node configuration and split count do not match

What it means

`Node::compute_splits` pairs the pane_grid `Node` tree with a `Count` tree while walking, and hits an incompatible node/count combination (e.g. `Node::Pane` with `Count::Split`). The two structures were built from different tree versions, so the library declares the case unreachable and panics.

Solutions

  1. Recompute the count tree from the exact same node tree right before computing splits.
  2. Persist and restore node + count trees as a single unit; validate the loaded structure by re-walking nodes.
  3. Ensure each split/close mutation regenerates counts before the next layout pass.
  4. If it occurs in stock usage, report as an internal desync bug with a reproduction.

Example fix

// before
splits_from_cache = cached_splits(state_at_load_time);
node.compute_splits(..., splits_from_cache, ...);
// after
splits = state.split_counts(); // recomputed from the same Node tree
node.compute_splits(..., splits, ...);
Defensive patterns

Strategy: validation

Validate before calling

fn splits_match(node: &Node, count: &Count) -> bool {
    match (node, count) {
        (Node::Split { a, b }, Count::Split { a: ca, b: cb }) => {
            splits_match(a, ca) && splits_match(b, cb)
        }
        (Node::Pane(_), Count::Pane) => true,
        _ => false,
    }
}

Type guard

fn is_valid_pair(node: &Node, count: &Count) -> bool {
    !matches!(
        (node, count),
        (Node::Split { .. }, Count::Pane) | (Node::Pane(_), Count::Split { .. })
    )
}

Try / catch

// Guard before calling split_regions
assert!(splits_match(&node, &count), "regenerate split counts from the node tree");
node.compute_splits(...);

Prevention

When it happens

Trigger: Calling `split_regions`/layout code where the split-count tree does not mirror the current node tree: a split was added or removed after counts were computed, or a reconstructed node tree disagrees with persisted counts.

Common situations: Restoring a saved pane layout where the node tree was edited (splits added/removed) without regenerating counts; concurrent mutation of pane state; mismatched snapshots in custom layout tooling.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of iced-rs/iced@d146509d89 (2026-09-11). Data as JSON: /api/errors/0376ec0016c83e29. Report an issue: GitHub.

Appendix: source

Thrown at widget/src/pane_grid/node.rs:340

                    Axis::Vertical => (count_a.vertical(), count_b.vertical()),
                };

                let (region_a, region_b, ratio) = axis.split(
                    current,
                    *ratio,
                    spacing,
                    min_size * (a_factor + 1) as f32 + spacing * a_factor as f32,
                    min_size * (b_factor + 1) as f32 + spacing * b_factor as f32,
                );

                let _ = splits.insert(*id, (*axis, *current, ratio));

                a.compute_splits(spacing, min_size, &region_a, count_a, splits);
                b.compute_splits(spacing, min_size, &region_b, count_b, splits);
            }
            (Node::Pane(_), Count::Pane) => {}
            _ => {
                unreachable!("Node configuration and split count do not match")
            }
        }
    }
}

impl std::hash::Hash for Node {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        match self {
            Node::Split {
                id,
                axis,
                ratio,
                a,
                b,
            } => {
                id.hash(state);
                axis.hash(state);
                ((ratio * 100_000.0) as u32).hash(state);

View on GitHub (pinned to d146509d89)