bevyengine/bevy · error · EvenCoreError

Cannot create an EvenCore over an unbounded domain

Error message

Cannot create an EvenCore over an unbounded domain

What it means

EvenCoreError::UnboundedDomain is returned by EvenCore::new when the supplied Interval is unbounded — an endpoint of -INF or +INF (e.g. Interval::EVERYTHING). EvenCore must place samples at even fractions across the domain, which is impossible over an infinite span, so the domain must be a bounded interval.

Source

Thrown at crates/bevy_math/src/curve/cores.rs:150

    ///
    /// # Invariants
    /// This must always have a length of at least 2.
    pub samples: Vec<T>,
}

/// An error indicating that an [`EvenCore`] could not be constructed.
#[derive(Debug, Error)]
#[error("Could not construct an EvenCore")]
pub enum EvenCoreError {
    /// Not enough samples were provided.
    #[error("Need at least two samples to create an EvenCore, but {samples} were provided")]
    NotEnoughSamples {
        /// The number of samples that were provided.
        samples: usize,
    },

    /// Unbounded domains are not compatible with `EvenCore`.
    #[error("Cannot create an EvenCore over an unbounded domain")]
    UnboundedDomain,
}

#[cfg(feature = "alloc")]
impl<T> EvenCore<T> {
    /// Create a new [`EvenCore`] from the specified `domain` and `samples`. The samples are
    /// regarded to be evenly spaced within the given domain interval, so that the outermost
    /// samples form the boundary of that interval. An error is returned if there are not at
    /// least 2 samples or if the given domain is unbounded.
    #[inline]
    pub fn new(
        domain: Interval,
        samples: impl IntoIterator<Item = T>,
    ) -> Result<Self, EvenCoreError> {
        let samples: Vec<T> = samples.into_iter().collect();
        if samples.len() < 2 {
            return Err(EvenCoreError::NotEnoughSamples {
                samples: samples.len(),

View on GitHub (pinned to 396ca72708)

Solutions

  1. Pass a bounded interval, e.g. Interval::new(0.0, duration)? where duration is finite.
  2. If data is unbounded, clamp it first: pick the time window you actually care about and construct the core over that.
  3. For arbitrary-time sparse samples, use UnevenCore instead, which has no bounded-domain requirement.

Example fix

// before
let core = EvenCore::new(Interval::EVERYTHING, samples); // Err(UnboundedDomain)

// after
let domain = Interval::new(0.0, samples.len() as f32 - 1.0)?; // bounded span
let core = EvenCore::new(domain, samples)?;
Defensive patterns

Strategy: validation

Validate before calling

if domain.is_bounded() {
    let core = EvenCore::new(domain, samples)?;
} // else clamp to a finite window first

Try / catch

let core = match EvenCore::new(domain, samples) {
    Ok(core) => core,
    Err(EvenCoreError::UnboundedDomain) => {
        let window = Interval::new(0.0, 1.0)?; // fall back to a sane finite window
        EvenCore::new(window, samples)?
    }
    Err(e) => return Err(e.into()),
};

Prevention

When it happens

Trigger: EvenCore::new(Interval::EVERYTHING, samples); passing an Interval built with infinite endpoints; deriving a domain from unclamped animation/physics times (t in 0..INF) and forwarding it into an even-sampled curve constructor.

Common situations: Using Interval::EVERYTHING as a 'default' domain; curves for animations without a defined duration; domains computed from a max time that came out as f32::INFINITY due to division by zero.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/dedc84e73f9d740b. Report an issue: GitHub.