bevyengine/bevy · error · MeshToMeshletMeshConversionError

Mesh has no indices

Error message

Mesh has no indices

What it means

`validate_input_mesh` in crates/bevy_pbr/src/meshlet/from_mesh.rs:274 requires `mesh.indices()` to return `Some(Indices::U16(_))` or `Some(Indices::U32(_))` before `MeshletMesh::from_mesh` can run. Meshletization works on triangle index lists, so a mesh with only a vertex buffer (no index buffer) is rejected with `MeshToMeshletMeshConversionError::MeshMissingIndices`.

Source

Thrown at crates/bevy_pbr/src/meshlet/from_mesh.rs:1100

// https://www.w3.org/TR/WGSL/#pack2x16snorm-builtin
fn pack2x16snorm(v: Vec2) -> u32 {
    let v = v.clamp(Vec2::NEG_ONE, Vec2::ONE);
    let v = (v * 32767.0 + 0.5).floor().as_i16vec2();
    bytemuck::cast(v)
}

/// An error produced by [`MeshletMesh::from_mesh`].
#[derive(Error, Debug)]
pub enum MeshToMeshletMeshConversionError {
    #[error("Mesh primitive topology is not TriangleList")]
    WrongMeshPrimitiveTopology,
    #[error("Mesh vertex attributes must be {required:?}, but got {provided:?}")]
    WrongMeshVertexAttributes {
        required: [MeshVertexAttribute; 3],
        provided: Vec<MeshVertexAttribute>,
    },
    #[error("Mesh has no indices")]
    MeshMissingIndices,
}

View on GitHub (pinned to 396ca72708)

Solutions

  1. Check `mesh.indices()` in a debug assert before converting
  2. If you only have vertices, insert a sequential index list: `mesh.insert_indices(Indices::U32((0..vertex_count as u32).collect()))`
  3. If you have triangle data elsewhere, build and insert the index buffer before `from_mesh`

Example fix

// before: vertex-only mesh -> MeshMissingIndices
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList);
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);

// after: add an index buffer
let vertex_count = positions.len() as u32;
mesh.insert_indices(Indices::U32((0..vertex_count).collect()));
Defensive patterns

Strategy: validation

Validate before calling

if mesh.indices().is_none() {
    let count = mesh.count_vertices();
    mesh.insert_indices(Indices::U32((0..count as u32).collect()));
}
let meshlet = MeshletMesh::from_mesh(mesh, &viewer)?;

Try / catch

match MeshletMesh::from_mesh(mesh, &viewer) {
    Err(MeshToMeshletMeshConversionError::MeshMissingIndices) => {
        warn!(?asset_path, "mesh has no indices; skipping meshlet conversion");
        // fall back to rendering the plain Mesh
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling `MeshletMesh::from_mesh` on a mesh built without `mesh.insert_indices(...)` — custom procedural geometry where only `insert_attribute(Mesh::ATTRIBUTE_POSITION, ...)` was called, or a triangle soup that never got an index list.

Common situations: Hand-rolled mesh builders (terrain chunks, procedural geometry loaders) that skip the index step; meshes converted from formats that store only vertex data; refactors that drop the `insert_indices` call.

Related errors


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