slint-ui/slint · error
constraint must have binding
Error message
constraint must have binding
What it means
This panic fires in `merge_explicit_constraints` (internal/compiler/passes/default_geometry.rs:345), called from `gen_layout_info_prop` while generating layout info for elements with explicit layout constraints. For each restriction the code fetches the element's binding for the constraint property (e.g. `min-width`, `preferred-height`) and asserts a binding exists. A missing binding means a constraint was registered in the layout analysis without an actual property binding — an inconsistent compiler state.
Solutions
- Set explicit layout constraints directly with property bindings (e.g. `min-width: 100px;`) rather than via intermediate indirections.
- Test with the latest stable Slint compiler to rule out a regression; downgrade if a nightly fails.
- Simplify the layout — split deeply nested or unusually constrained layouts into sub-components.
- Contributors: verify `register_property_with_let`/constraint registration always creates a binding before `merge_explicit_constraints` reads it.
Example fix
// before
Rectangle { width: parent.width * 0.5; } // implicit, no constraint binding
// after
Rectangle { min-width: 100px; preferred-width: 200px; } Defensive patterns
Strategy: validation
Validate before calling
// Prefer real bindings for every constraint property you declare
fn constraints_have_bindings(element_props: &[&str]) -> bool {
["min-width", "min-height", "max-width", "max-height", "preferred-width", "preferred-height"]
.iter().all(|c| !element_props.contains(c) || true /* verify a binding exists for each declared constraint */)
} Prevention
- Declare constraints as direct property bindings, not via computed/implicit values only.
- Avoid mixing heavy implicit sizing with explicit constraints in one layout.
- Test layouts against stable Slint releases in CI.
When it happens
Trigger: Compiling a layout (Row/Column/GridLayout or a component with explicit min/max/preferred size constraints) where a restriction was recorded for an element/property pair whose binding was removed or never created — e.g. constraints set on elements without real bindings, bindings consumed/cleared by an earlier pass, or two-way binding edge cases.
Common situations: Nightly compiler regressions in default geometry; .slint layouts combining percentage/implicit sizes with explicit constraints in unusual ways; contributor changes to binding creation or constraint collection.
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
- Component should cleanly upgrade here
- element without a size
- EmbedTextures builds the shared font collection
- internal compiler error: more than one strong reference…
- LibGlobal not found
AI-assisted analysis of slint-ui/slint@3a7e700487 (2026-09-16).
Data as JSON: /api/errors/1fc39bcc41e02c3d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/compiler/passes/default_geometry.rs:349
p.clone(),
Expression::StructFieldAccess {
base: Expression::ReadLocalVariable {
name: unique_name.clone(),
ty: ty.clone(),
}
.into(),
name: p.clone(),
},
)
})
.collect::<BTreeMap<_, _>>();
for (nr, s) in constraints.for_each_restrictions(orientation) {
let e = nr
.element()
.borrow()
.binding(nr.name())
.expect("constraint must have binding")
.expression
.clone();
debug_assert!(!matches!(e, Expression::Invalid));
values.insert(s.into(), e);
}
*expr = Expression::CodeBlock([store, Expression::Struct { ty: s.clone(), values }].into());
}
}
fn explicit_layout_info(e: &ElementRc, orientation: Orientation) -> Expression {
let mut values = BTreeMap::new();
let (size, orient) = match orientation {
Orientation::Horizontal => ("width", "horizontal"),
Orientation::Vertical => ("height", "vertical"),
};
for (k, v) in [
("min", format_smolstr!("min-{size}")),
("max", format_smolstr!("max-{size}")),View on GitHub (pinned to 3a7e700487)