bevyengine/bevy · error

Meshes used with Extrusions must have a primitive topology o

Error message

Meshes used with Extrusions must have a primitive topology of `PrimitiveTopology::TriangleList`

What it means

Panic in Extrusion meshing (crates/bevy_mesh/src/primitives/extrusion.rs:226). When building the back face of an extrusion, Bevy matches on the base mesh's index buffer and primitive topology; a non-TriangleList topology falls into the catch-all arm and panics, because the face-flipping and merge logic is written exclusively for triangle lists.

Source

Thrown at crates/bevy_mesh/src/primitives/extrusion.rs:226

            }

            // By swapping the first and second indices of each triangle we invert the winding order thus making the mesh visible from the other side
            if let Some(indices) = back_face.indices_mut() {
                match topology {
                    PrimitiveTopology::TriangleList => match indices {
                        Indices::U16(indices) => {
                            for [a, b, _] in indices.as_chunks_mut().0 {
                                core::mem::swap(a, b);
                            }
                        }
                        Indices::U32(indices) => {
                            for [a, b, _] in indices.as_chunks_mut().0 {
                                core::mem::swap(a, b);
                            }
                        }
                    },
                    _ => {
                        panic!("Meshes used with Extrusions must have a primitive topology of `PrimitiveTopology::TriangleList`");
                    }
                };
            }
            back_face
        };

        // An extrusion of depth 0 does not need a mantel
        if self.half_depth == 0. {
            front_face.merge(&back_face).unwrap();
            return front_face;
        }

        let mantel = {
            let Some(VertexAttributeValues::Float32x3(cap_verts)) =
                front_face.attribute(Mesh::ATTRIBUTE_POSITION)
            else {
                panic!("The base mesh did not have vertex positions");
            };

View on GitHub (pinned to 396ca72708)

Solutions

  1. Make the custom base shape's builder return a Mesh created with PrimitiveTopology::TriangleList
  2. If you have strip data, convert indices to a triangle list before the extrusion path sees them
  3. Add an assert in your builder tests that the topology equals TriangleList when Extrudable is implemented

Example fix

// before: custom base shape built as a strip
impl Meshable for MyShape {
    fn build(&self) -> MeshBuilder {
        MeshBuilder::new(&self.primitive, 3).topology(PrimitiveTopology::TriangleStrip)
    }
}
Extrusion::new(MyShape::default(), 2.0).mesh().build(); // panic at extrusion.rs:226

// after: triangle-list base mesh
MeshBuilder::new(&self.primitive, 3) // default topology is TriangleList
Defensive patterns

Strategy: validation

Validate before calling

// For custom Extrudable base shapes: guard before extruding
fn extrudable_base(mesh: &Mesh) -> bool {
    matches!(mesh.primitive_topology(), PrimitiveTopology::TriangleList)
}

assert!(extrudable_base(&my_shape_mesh)); // in tests / debug builds

Type guard

fn triangle_list_builder(builder: MeshBuilder) -> MeshBuilder {
    debug_assert_eq!(builder.primitive_topology, PrimitiveTopology::TriangleList);
    builder
}

Prevention

When it happens

Trigger: Calling Extrusion::new(base_shape, depth).mesh() where the base shape's Meshable output uses PrimitiveTopology::TriangleStrip (or any non-TriangleList topology). All built-in 2D primitives emit TriangleList, so this is hit with custom Meshable/Extrudable implementations.

Common situations: Custom 2D primitives authored for strip rendering; a builder refactor that changed Mesh::new topology; copy-pasting a custom primitive from a strip-optimized codebase into an extrusion workflow.

Related errors


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