bevyengine/bevy · error · GenerateTangentsError
cannot generate tangents for {0:?}
Error message
cannot generate tangents for {0:?} What it means
GenerateTangentsError::UnsupportedTopology (crates/bevy_mesh/src/mikktspace.rs:65), returned by Mesh::compute_tangents / generate_tangents_for_mesh. The mikktspace tangent-generation algorithm walks triangles by index triplets, so the mesh must use PrimitiveTopology::TriangleList; any other topology is rejected with the offending variant embedded in the error.
Source
Thrown at crates/bevy_mesh/src/mikktspace.rs:65
fn tex_coord(&self, face: usize, vert: usize) -> [f32; 2] {
self.uvs[self.index(face, vert)]
}
fn set_tangent(
&mut self,
tangent_space: Option<bevy_mikktspace::TangentSpace>,
face: usize,
vert: usize,
) {
let idx = self.index(face, vert);
self.tangents[idx] = tangent_space.unwrap_or_default().tangent_encoded();
}
}
#[derive(Error, Debug)]
/// Failed to generate tangents for the mesh.
pub enum GenerateTangentsError {
#[error("cannot generate tangents for {0:?}")]
UnsupportedTopology(PrimitiveTopology),
#[error("missing indices")]
MissingIndices,
#[error("missing vertex attributes '{0}'")]
MissingVertexAttribute(&'static str),
#[error("the '{0}' vertex attribute should have {1:?} format")]
InvalidVertexAttributeFormat(&'static str, VertexFormat),
#[error("mesh not suitable for tangent generation")]
MikktspaceError(#[from] bevy_mikktspace::GenerateTangentSpaceError),
#[error("Mesh access error: {0}")]
MeshAccessError(#[from] MeshAccessError),
}
pub(crate) fn generate_tangents_for_mesh(
mesh: &Mesh,
) -> Result<Vec<[f32; 4]>, GenerateTangentsError> {
match mesh.primitive_topology() {
PrimitiveTopology::TriangleList => {}View on GitHub (pinned to 396ca72708)
Solutions
- Build the mesh with PrimitiveTopology::TriangleList before compute_tangents()
- Convert strip indices to triangle-list indices (expand each consecutive triple) and re-insert via insert_indices
- Skip tangent generation for non-triangle meshes (tangents are meaningless for lines/points)
Example fix
// before let mut mesh = Mesh::new(PrimitiveTopology::TriangleStrip, RenderAssetUsages::default()); // ...positions, normals, uvs, indices... mesh.compute_tangents(); // Err(UnsupportedTopology(TriangleStrip)) // after let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default()); // ...same attributes... mesh.compute_tangents().unwrap();
Defensive patterns
Strategy: validation
Validate before calling
if mesh.primitive_topology() == PrimitiveTopology::TriangleList {
mesh.compute_tangents()?;
} else {
// convert to triangle list or skip tangents
} Type guard
fn is_triangle_list(mesh: &Mesh) -> bool {
matches!(mesh.primitive_topology(), PrimitiveTopology::TriangleList)
} Try / catch
if let Err(GenerateTangentsError::UnsupportedTopology(topo)) = mesh.compute_tangents() {
bevy::log::error!("compute_tangents needs TriangleList, got {topo:?}");
} Prevention
- Use PrimitiveTopology::TriangleList for any mesh that will be normal-mapped
- Expand strip indices to triangle lists at import time
- Remember points/lines cannot have meaningful tangents at all
When it happens
Trigger: Calling mesh.compute_tangents() on a mesh created with PrimitiveTopology::TriangleStrip, PointList, LineList or LineStrip. The match at mikktspace.rs:83 sends every non-TriangleList topology into this error before any attribute is read.
Common situations: Normal-mapping a strip-optimized custom mesh to save index memory; accidentally reusing a 2D/line mesh constructor for a 3D shaded asset; importers that emit strips for legacy data.
Related errors
- Incompatible primitive topologies: {:?} and {:?}
- missing indices
- missing vertex attributes '{0}'
- the '{0}' vertex attribute should have {1:?} format
- mesh not suitable for tangent generation
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/4792e406ea0a02a8.
Report an issue: GitHub.