{"record":{"id":"ba60ca6a5566baab","repo":"bevyengine/bevy","slug":"invalid-knots-all-knots-are-equal","errorCode":null,"errorMessage":"Invalid knots: all knots are equal","messagePattern":"Invalid knots: all knots are equal","errorType":"exception","errorClass":"CubicNurbsError","httpStatus":null,"severity":"error","filePath":"crates/bevy_math/src/cubic_splines/mod.rs","lineNumber":540,"sourceCode":"}\n\n/// Error during construction of [`CubicNurbs`]\n#[derive(Clone, Debug, Error)]\npub enum CubicNurbsError {\n    /// Provided the wrong number of knots.\n    #[error(\"Wrong number of knots: expected {expected}, provided {provided}\")]\n    KnotsNumberMismatch {\n        /// Expected number of knots\n        expected: usize,\n        /// Provided number of knots\n        provided: usize,\n    },\n    /// The provided knots had a descending knot pair. Subsequent knots must\n    /// either increase or stay the same.\n    #[error(\"Invalid knots: contains descending knot pair\")]\n    DescendingKnots,\n    /// The provided knots were all equal. Knots must contain at least one increasing pair.\n    #[error(\"Invalid knots: all knots are equal\")]\n    ConstantKnots,\n    /// Provided a different number of weights and control points.\n    #[error(\"Incorrect number of weights: expected {expected}, provided {provided}\")]\n    WeightsNumberMismatch {\n        /// Expected number of weights\n        expected: usize,\n        /// Provided number of weights\n        provided: usize,\n    },\n    /// The number of control points provided is less than 4.\n    #[error(\"Not enough control points, at least 4 are required, {provided} were provided\")]\n    NotEnoughControlPoints {\n        /// The number of control points provided\n        provided: usize,\n    },\n}\n\n/// Non-uniform Rational B-Splines (NURBS) are a powerful generalization of the [`CubicBSpline`] which can","sourceCodeStart":522,"sourceCodeEnd":558,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_math/src/cubic_splines/mod.rs#L522-L558","documentation":"CubicNurbsError::ConstantKnots is returned by CubicNurbs::new when every knot in the provided knot vector equals its neighbor — i.e. all knots are the same value. NURBS evaluation needs at least one strictly increasing knot pair to define a nonzero parameter range; a constant vector gives zero curve length and division by zero downstream, so construction is rejected. Note the vector must still be non-descending (n + 4 entries for n control points), and at least one adjacent pair must strictly increase.","triggerScenarios":"Calling CubicNurbs::new(points, weights, Some(vec![0.0; n + 4])) with an all-identical knot vector; generating knots programmatically where the increment is computed as 0 (e.g. dividing by a zero span or a constant generator function).","commonSituations":"Authoring NURBS data by hand in an editor/exporter and copying one knot value across; procedural knot generation with a `step` that collapses to zero due to an integer division or a bad min/max normalization.","solutions":["Pass `None` for knots to use the default open_uniform_knots, which is always valid.","Fix the vector so it is non-descending and contains at least one strict increase, e.g. open uniform [0,0,0,0,1,1,1,1] for 4 control points.","If knots come from a generator, debug why the delta is zero: print min/max before constructing."],"exampleFix":"// before\nlet n = control_points.len();\nlet nurbs = CubicNurbs::new(control_points, None, Some(vec![0.5; n + 4]))?; // ConstantKnots\n\n// after\nlet nurbs = CubicNurbs::new(control_points, None, None)?; // open uniform knots\n// or explicitly:\nlet knots = CubicNurbs::open_uniform_knots(n).unwrap();\nlet nurbs = CubicNurbs::new(control_points, None, Some(knots))?;","handlingStrategy":"try-catch","validationCode":"fn knots_valid(knots: &[f32]) -> bool {\n    knots.windows(2).all(|w| w[0] <= w[1]) // non-descending\n        && knots.windows(2).any(|w| w[0] < w[1]) // at least one strict increase\n}\n\n// then: if knots_valid(&knots) { CubicNurbs::new(points, None, Some(knots))? } else { ... }","typeGuard":null,"tryCatchPattern":"match CubicNurbs::new(&points, None, Some(knots.clone())) {\n    Ok(nurbs) => nurbs,\n    Err(CubicNurbsError::ConstantKnots) => {\n        // fall back to default open uniform knots\n        CubicNurbs::new(&points, None, None)?\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Prefer passing `None` for knots unless you specifically need non-uniform parameterization.","Validate knot vectors at asset load: non-descending, length n+4, at least one strict increase.","When generating knots procedurally, assert the computed span (max - min) is > 0."],"tags":["rust","bevy","math","spline","nurbs","runtime"],"backgroundTag":"invalid-spline-parameters","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}