{"record":{"id":"9a05ccc79c46c19c","repo":"bevyengine/bevy","slug":"the-resulting-interval-would-be-invalid-empty-or","errorCode":null,"errorMessage":"The resulting interval would be invalid (empty or with a NaN endpoint)","messagePattern":"The resulting interval would be invalid \\(empty or with a NaN endpoint\\)","errorType":"exception","errorClass":"InvalidIntervalError","httpStatus":null,"severity":"error","filePath":"crates/bevy_math/src/curve/interval.rs","lineNumber":37,"sourceCode":"#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]\n#[cfg_attr(feature = \"serialize\", derive(serde::Serialize, serde::Deserialize))]\n#[cfg_attr(\n    feature = \"bevy_reflect\",\n    derive(Reflect),\n    reflect(Debug, PartialEq, Clone)\n)]\n#[cfg_attr(\n    all(feature = \"serialize\", feature = \"bevy_reflect\"),\n    reflect(Serialize, Deserialize)\n)]\npub struct Interval {\n    start: f32,\n    end: f32,\n}\n\n/// An error that indicates that an operation would have returned an invalid [`Interval`].\n#[derive(Debug, Error)]\n#[error(\"The resulting interval would be invalid (empty or with a NaN endpoint)\")]\npub struct InvalidIntervalError;\n\n/// An error indicating that spaced points could not be extracted from an unbounded interval.\n#[derive(Debug, Error)]\n#[error(\"Cannot extract spaced points from an unbounded interval\")]\npub struct SpacedPointsError;\n\n/// An error indicating that a linear map between intervals could not be constructed because of\n/// unboundedness.\n#[derive(Debug, Error)]\n#[error(\"Could not construct linear function to map between intervals\")]\npub(super) enum LinearMapError {\n    /// The source interval being mapped out of was unbounded.\n    #[error(\"The source interval is unbounded\")]\n    SourceUnbounded,\n\n    /// The target interval being mapped into was unbounded.\n    #[error(\"The target interval is unbounded\")]","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_math/src/curve/interval.rs#L19-L55","documentation":"InvalidIntervalError is returned whenever an operation would produce an empty or NaN-endpoint Interval. Interval::new(start, end) rejects start > end and any NaN argument; Interval::intersect rejects producing an empty result (disjoint intervals); the interval()/TryFrom<RangeInclusive> helpers and curve adaptors like zip (intersecting two curve domains) can surface it too. Intervals must satisfy start <= end with both endpoints finite/valid.","triggerScenarios":"Interval::new(end, start) with swapped arguments; interval(a, b) where a > b; passing NaN (e.g. from 0.0/0.0); curve1.zip(curve2) on curves with disjoint domains; intersect(Interval::new(0.,1.)?, Interval::new(2.,3.)?) yielding empty.","commonSituations":"Computing domain endpoints from data where min/max were never ordered (single-element iterates, reversed loops); NaN leaking from trig or normalization math; zipping two animations whose time ranges don't overlap.","solutions":["Order endpoints before constructing: Interval::new(a.min(b), a.max(b)).","Guard against NaN: check a.is_finite() && b.is_finite() before calling.","For zip/intersect of possibly-disjoint ranges, check overlap first (max(starts) <= min(ends)) and handle the disjoint case explicitly instead of unwrapping."],"exampleFix":"// before\nlet domain = Interval::new(t_max, t_min)?; // swapped -> InvalidIntervalError\nlet zipped = curve_a.zip(curve_b)?; // disjoint domains -> InvalidIntervalError\n\n// after\nlet domain = Interval::new(t_min.min(t_max), t_min.max(t_max))?;\nlet zipped = if curve_a.domain().intersect(curve_b.domain()).is_ok() {\n    Some(curve_a.zip(curve_b)?)\n} else {\n    None // no overlap: skip or report\n};","handlingStrategy":"validation","validationCode":"fn valid_interval(a: f32, b: f32) -> bool {\n    a.is_finite() && b.is_finite() && a <= b\n}\n\nif valid_interval(start, end) {\n    let interval = Interval::new(start, end)?;\n}","typeGuard":null,"tryCatchPattern":"let interval = match Interval::new(start, end) {\n    Ok(iv) => iv,\n    Err(InvalidIntervalError) => Interval::new(end, start)?, // swapped inputs: normalize order\n};","preventionTips":["Always order endpoints: Interval::new(a.min(b), a.max(b)).","Reject NaN early wherever times/positions are computed (0.0/0.0, unclamped trig).","Before zip/intersect, check overlap: max(a.start, b.start) <= min(a.end, b.end), and handle the disjoint case explicitly instead of unwrapping the Result."],"tags":["rust","bevy","math","curve","interval","nan","runtime"],"backgroundTag":"invalid-interval","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"}