{"record":{"id":"ef50bd905763bb94","repo":"bevyengine/bevy","slug":"meshes-used-with-extrusions-must-have-a-primitive","errorCode":null,"errorMessage":"Meshes used with Extrusions must have a primitive topology of `PrimitiveTopology::TriangleList`","messagePattern":"Meshes used with Extrusions must have a primitive topology of `PrimitiveTopology::TriangleList`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/primitives/extrusion.rs","lineNumber":226,"sourceCode":"            }\n\n            // By swapping the first and second indices of each triangle we invert the winding order thus making the mesh visible from the other side\n            if let Some(indices) = back_face.indices_mut() {\n                match topology {\n                    PrimitiveTopology::TriangleList => match indices {\n                        Indices::U16(indices) => {\n                            for [a, b, _] in indices.as_chunks_mut().0 {\n                                core::mem::swap(a, b);\n                            }\n                        }\n                        Indices::U32(indices) => {\n                            for [a, b, _] in indices.as_chunks_mut().0 {\n                                core::mem::swap(a, b);\n                            }\n                        }\n                    },\n                    _ => {\n                        panic!(\"Meshes used with Extrusions must have a primitive topology of `PrimitiveTopology::TriangleList`\");\n                    }\n                };\n            }\n            back_face\n        };\n\n        // An extrusion of depth 0 does not need a mantel\n        if self.half_depth == 0. {\n            front_face.merge(&back_face).unwrap();\n            return front_face;\n        }\n\n        let mantel = {\n            let Some(VertexAttributeValues::Float32x3(cap_verts)) =\n                front_face.attribute(Mesh::ATTRIBUTE_POSITION)\n            else {\n                panic!(\"The base mesh did not have vertex positions\");\n            };","sourceCodeStart":208,"sourceCodeEnd":244,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/primitives/extrusion.rs#L208-L244","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Make the custom base shape's builder return a Mesh created with PrimitiveTopology::TriangleList","If you have strip data, convert indices to a triangle list before the extrusion path sees them","Add an assert in your builder tests that the topology equals TriangleList when Extrudable is implemented"],"exampleFix":"// before: custom base shape built as a strip\nimpl Meshable for MyShape {\n    fn build(&self) -> MeshBuilder {\n        MeshBuilder::new(&self.primitive, 3).topology(PrimitiveTopology::TriangleStrip)\n    }\n}\nExtrusion::new(MyShape::default(), 2.0).mesh().build(); // panic at extrusion.rs:226\n\n// after: triangle-list base mesh\nMeshBuilder::new(&self.primitive, 3) // default topology is TriangleList","handlingStrategy":"validation","validationCode":"// For custom Extrudable base shapes: guard before extruding\nfn extrudable_base(mesh: &Mesh) -> bool {\n    matches!(mesh.primitive_topology(), PrimitiveTopology::TriangleList)\n}\n\nassert!(extrudable_base(&my_shape_mesh)); // in tests / debug builds","typeGuard":"fn triangle_list_builder(builder: MeshBuilder) -> MeshBuilder {\n    debug_assert_eq!(builder.primitive_topology, PrimitiveTopology::TriangleList);\n    builder\n}","tryCatchPattern":null,"preventionTips":["Extrusion requires TriangleList base meshes — never emit strips from custom 2D builders","Assert the topology in your builder's unit tests when implementing Extrudable","Convert any strip-based geometry to triangle lists before it reaches extrusion"],"tags":["bevy","mesh","extrusion","primitive-topology","mismatch","panic"],"backgroundTag":"primitive-topology-mismatch","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}