bevyengine/bevy · error · VecInterpolateError

cannot interpolate between two arrays of different lengths

Error message

cannot interpolate between two arrays of different lengths

What it means

Vec<T>'s TryStableInterpolate requires self and other to have equal lengths; a length difference returns MismatchedLength, while element-level failures are wrapped in Inner(E) (crates/bevy_math/src/common_traits.rs:633). Interpolating element-wise between arrays of different sizes has no defined result, so it fails instead of guessing.

Source

Thrown at crates/bevy_math/src/common_traits.rs:633

impl<T: StableInterpolate> TryStableInterpolate for T {
    type Error = Infallible;
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
        Ok(self.interpolate_stable(other, t))
    }

    fn try_interpolate_stable_assign(&mut self, other: &Self, t: f32) -> Result<(), Self::Error> {
        self.interpolate_stable_assign(other, t);
        Ok(())
    }
}

/// Errors produced when interpolating dynamically-sized arrays
#[cfg(feature = "alloc")]
#[derive(Clone, Debug, Error)]
pub enum VecInterpolateError<E> {
    /// Produced when arrays to be interpolated are of different lengths
    #[error("cannot interpolate between two arrays of different lengths")]
    MismatchedLength,
    /// Produced when an error occurs interpolating an array element
    #[error(transparent)]
    Inner(E),
}

#[cfg(feature = "alloc")]
impl<E, T: TryStableInterpolate<Error = E>> TryStableInterpolate for alloc::vec::Vec<T> {
    type Error = VecInterpolateError<E>;
    fn try_interpolate_stable(&self, other: &Self, t: f32) -> Result<Self, Self::Error> {
        if self.len() == other.len() {
            (0..self.len())
                .map(|i| self[i].try_interpolate_stable(&other[i], t))
                .collect::<Result<alloc::vec::Vec<_>, _>>()
                .map_err(VecInterpolateError::Inner)
        } else {
            Err(VecInterpolateError::MismatchedLength)
        }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Compare lengths before interpolating; re-capture both endpoints whenever the count changes.
  2. On MismatchedLength, snap to the target Vec instead of blending.
  3. Handle Inner(e) separately for element-level failures such as MismatchedUnitsError.

Example fix

// before
let blended = a.try_interpolate_stable(&b, t).unwrap(); // panics when lengths differ

// after
let blended = if a.len() == b.len() {
    a.try_interpolate_stable(&b, t).unwrap_or_else(|_| b.clone())
} else {
    b.clone()
};
Defensive patterns

Strategy: validation

Validate before calling

use bevy_math::TryStableInterpolate;

fn can_blend<T: TryStableInterpolate>(a: &Vec<T>, b: &Vec<T>) -> bool {
    a.len() == b.len()
}

let blended = if can_blend(&a, &b) {
    a.try_interpolate_stable(&b, t).unwrap_or_else(|_| b.clone())
} else {
    b.clone()
};

Try / catch

match a.try_interpolate_stable(&b, t) {
    Ok(v) => { /* use v */ }
    Err(VecInterpolateError::MismatchedLength) => { /* snap to b */ }
    Err(VecInterpolateError::Inner(e)) => { /* handle element error e */ }
}

Prevention

When it happens

Trigger: Calling try_interpolate_stable on two Vecs whose lengths differ — e.g. captured lists of styles or transforms where entries were added or removed between the two snapshots.

Common situations: Animating lists of UI children whose count changed mid-animation; diff-based tween systems capturing start/end states at different times; serde-loaded sequences that drift in length.

Related errors


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