bevyengine/bevy · error · CubicNurbsError
Invalid knots: contains descending knot pair
Error message
Invalid knots: contains descending knot pair
What it means
Knot vectors must be a non-decreasing sequence: any adjacent pair with knots[i] > knots[i+1] returns DescendingKnots (cubic_splines/mod.rs:667-669). Repeated values are allowed (knot multiplicity, useful for sharp corners); only decreases are invalid.
Source
Thrown at crates/bevy_math/src/cubic_splines/mod.rs:537
Ok(CubicCurve { segments })
}
}
}
/// Error during construction of [`CubicNurbs`]
#[derive(Clone, Debug, Error)]
pub enum CubicNurbsError {
/// Provided the wrong number of knots.
#[error("Wrong number of knots: expected {expected}, provided {provided}")]
KnotsNumberMismatch {
/// Expected number of knots
expected: usize,
/// Provided number of knots
provided: usize,
},
/// The provided knots had a descending knot pair. Subsequent knots must
/// either increase or stay the same.
#[error("Invalid knots: contains descending knot pair")]
DescendingKnots,
/// The provided knots were all equal. Knots must contain at least one increasing pair.
#[error("Invalid knots: all knots are equal")]
ConstantKnots,
/// Provided a different number of weights and control points.
#[error("Incorrect number of weights: expected {expected}, provided {provided}")]
WeightsNumberMismatch {
/// Expected number of weights
expected: usize,
/// Provided number of weights
provided: usize,
},
/// The number of control points provided is less than 4.
#[error("Not enough control points, at least 4 are required, {provided} were provided")]
NotEnoughControlPoints {
/// The number of control points provided
provided: usize,
},View on GitHub (pinned to 396ca72708)
Solutions
- Sort the knot vector ascending before passing it (stable repeats preserved).
- Validate with knots.windows(2).all(|w| w[0] <= w[1]) at load time.
- Pass None for knots if custom parameterization is not required.
Example fix
// before let knots = [5.0, 1.0, 2.0, 3.0, 4.0, 4.0, 5.0, 0.0]; // descending pairs -> error // after let mut knots = knots; knots.sort_by(|a, b| a.partial_cmp(b).unwrap()); let nurbs = CubicNurbs::new(pts, None, Some(knots))?;
Defensive patterns
Strategy: validation
Validate before calling
fn knots_nondecreasing(knots: &[f32]) -> bool {
knots.windows(2).all(|w| w[0] <= w[1])
}
let knots = {
let mut k = knots.to_vec();
k.sort_by(|a, b| a.partial_cmp(b).unwrap());
k
};
assert!(knots_nondecreasing(&knots)); Try / catch
match CubicNurbs::new(points, None, Some(knots)) {
Err(CubicNurbsError::DescendingKnots) => { /* sort knots ascending and retry */ }
Ok(n) => { /* use n */ }
Err(e) => warn!("{e}"),
} Prevention
- Sort imported knot vectors non-decreasing at load time.
- Remember repeats are allowed (multiplicity), only decreases are invalid.
- Add a windows(2) monotonicity check to asset validation.
When it happens
Trigger: Passing an unsorted or hand-edited knot vector; importing parameterizations that run descending; sign mistakes or transposed values in long vectors.
Common situations: Manually authored knot arrays in level/tooling data; knots exported from DCC tools with reversed parameters; copy-paste errors in 8+ element vectors.
Related errors
- Wrong number of knots: expected {expected}, provided {provid
- Invalid knots: all knots are equal
- Incorrect number of weights: expected {expected}, provided {
- Not enough control points, at least 4 are required, {provide
- Unable to generate cubic curve: at least one set of control
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/0d0316d90ef42759.
Report an issue: GitHub.