bevyengine/bevy · error

point cloud must contain at least one point for Aabb3d const

Error message

point cloud must contain at least one point for Aabb3d construction

What it means

Aabb3d::from_point_cloud panics via .expect when the input iterator yields no items (crates/bevy_math/src/bounding/bounded3d/mod.rs:101) — the min/max fold needs a first point to seed from. It is a panic by design, so empty iterators must be filtered before the call.

Source

Thrown at crates/bevy_math/src/bounding/bounded3d/mod.rs:101

    /// Computes the smallest [`Aabb3d`] containing the given set of points,
    /// transformed by the rotation and translation of the given isometry.
    ///
    /// # Panics
    ///
    /// Panics if the given set of points is empty.
    #[inline]
    pub fn from_point_cloud(
        isometry: impl Into<Isometry3d>,
        points: impl Iterator<Item = impl Into<Vec3A>>,
    ) -> Aabb3d {
        let isometry = isometry.into();

        // Transform all points by rotation
        let mut iter = points.map(|point| isometry.rotation * point.into());

        let first = iter
            .next()
            .expect("point cloud must contain at least one point for Aabb3d construction");

        let (min, max) = iter.fold((first, first), |(prev_min, prev_max), point| {
            (point.min(prev_min), point.max(prev_max))
        });

        Aabb3d {
            min: min + isometry.translation,
            max: max + isometry.translation,
        }
    }

    /// Computes the smallest [`BoundingSphere`] containing this [`Aabb3d`].
    #[inline]
    pub fn bounding_sphere(&self) -> BoundingSphere {
        let radius = self.min.distance(self.max) / 2.0;
        BoundingSphere::new(self.center(), radius)
    }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Materialize and check the iterator is non-empty before calling from_point_cloud.
  2. Skip or early-return for empty sets instead of computing bounds.
  3. Be careful not to consume an iterator before passing it (an already-drained iterator is empty).

Example fix

// before
let aabb = Aabb3d::from_point_cloud(iso, iter); // panics on empty iterator

// after
let collected: Vec<_> = iter.collect();
if collected.is_empty() {
    return;
}
let aabb = Aabb3d::from_point_cloud(iso, collected.into_iter());
Defensive patterns

Strategy: validation

Validate before calling

fn point_cloud_aabb3d(
    iso: impl Into<Isometry3d>,
    points: impl Iterator<Item = impl Into<Vec3A>>,
) -> Option<Aabb3d> {
    let points: Vec<_> = points.collect();
    if points.is_empty() {
        return None;
    }
    Some(Aabb3d::from_point_cloud(iso, points.into_iter()))
}

Prevention

When it happens

Trigger: Calling Aabb3d::from_point_cloud(isometry, iter) where iter is empty — e.g. an iterator over an empty vertex buffer, an emptied query, or a fully-filtered collection.

Common situations: Mesh bounds computed during async loading before vertex data exists; iterators consumed earlier so they yield nothing on the second pass; entity queries matching no entities.

Related errors


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