bevyengine/bevy · error · UnevenCoreError

Need at least two unique samples to create an UnevenCore, bu

Error message

Need at least two unique samples to create an UnevenCore, but {samples} were provided

What it means

UnevenCoreError::NotEnoughSamples is returned by UnevenCore::new when, after filtering out non-finite times, sorting, and deduplicating, fewer than 2 unique timed samples remain. Interpolation needs two distinct times to define a span. Note the count is post-processing, so 3 raw samples can still fail if two share a time and one is NaN.

Source

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

    ///
    /// # Invariants
    /// This must always have a length of at least 2, be sorted, and have no
    /// duplicated or non-finite times.
    pub times: Vec<f32>,

    /// The samples corresponding to the times for this curve.
    ///
    /// # Invariants
    /// This must always have the same length as `times`.
    pub samples: Vec<T>,
}

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

#[cfg(feature = "alloc")]
impl<T> UnevenCore<T> {
    /// Create a new [`UnevenCore`]. The given samples are filtered to finite times and
    /// sorted internally; if there are not at least 2 valid timed samples, an error will be
    /// returned.
    pub fn new(timed_samples: impl IntoIterator<Item = (f32, T)>) -> Result<Self, UnevenCoreError> {
        // Filter out non-finite sample times first so they don't interfere with sorting/deduplication.
        let mut timed_samples = timed_samples
            .into_iter()
            .filter(|(t, _)| t.is_finite())

View on GitHub (pinned to 396ca72708)

Solutions

  1. Ensure at least two samples with distinct, finite f32 times before constructing.
  2. Sanitize times: replace or drop NaN/INF timestamps at load time with an explicit policy.
  3. If timestamps can legitimately collide, aggregate them (e.g. keep the last) before building the core.

Example fix

// before
let core = UnevenCore::new(vec![ (0.0, a), (f32::NAN, b), (0.0, c) ])?; // NotEnoughSamples { samples: 1 }

// after
let times_samples: Vec<(f32, V)> = raw
    .into_iter()
    .filter(|(t, _)| t.is_finite())
    .collect();
assert!(times_samples.len() >= 2, "need >= 2 unique finite times");
let core = UnevenCore::new(times_samples)?;
Defensive patterns

Strategy: validation

Validate before calling

let cleaned: Vec<(f32, T)> = timed.into_iter().filter(|(t, _)| t.is_finite()).collect();
let unique_times = cleaned.iter().map(|(t, _)| t.to_bits()).collect::<std::collections::HashSet<_>>();
if unique_times.len() >= 2 {
    let core = UnevenCore::new(cleaned)?;
}

Try / catch

let core = match UnevenCore::new(timed_samples) {
    Ok(core) => core,
    Err(UnevenCoreError::NotEnoughSamples { samples }) if samples == 0 => {
        return Ok(()); // nothing recorded yet this frame; skip
    }
    Err(e) => return Err(e.into()),
};

Prevention

When it happens

Trigger: UnevenCore::new(vec![(0.0, a)]) with one sample; samples containing f32::NAN or f32::INFINITY timestamps that get filtered out; duplicated timestamps that dedup to a single unique time; empty input.

Common situations: Keyframe data with NaN times produced by upstream math (0/0, acos out of range); timestamp collisions from two events in the same frame; deserialized animation data where times failed to parse and defaulted to the same value.

Related errors


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