bevyengine/bevy · error · GenerateTangentsError
Mesh access error: {0}
Error message
Mesh access error: {0} What it means
GenerateTangentsError::MeshAccessError (crates/bevy_mesh/src/mikktspace.rs:75) propagates from the try_attribute_option calls at the start of generate_tangents_for_mesh. It is the render-world-extraction case: the mesh was created without MAIN_WORLD in its RenderAssetUsages, the renderer moved its data away, and tangent generation can no longer read POSITION/NORMAL/UV_0.
Source
Thrown at crates/bevy_mesh/src/mikktspace.rs:75
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 => {}
other => return Err(GenerateTangentsError::UnsupportedTopology(other)),
};
let positions = mesh.try_attribute_option(Mesh::ATTRIBUTE_POSITION)?.ok_or(
GenerateTangentsError::MissingVertexAttribute(Mesh::ATTRIBUTE_POSITION.name),
)?;
let VertexAttributeValues::Float32x3(positions) = positions else {
return Err(GenerateTangentsError::InvalidVertexAttributeFormat(
Mesh::ATTRIBUTE_POSITION.name,
VertexFormat::Float32x3,View on GitHub (pinned to 396ca72708)
Solutions
- Create the mesh with RenderAssetUsages::default() so CPU data survives extraction
- Run compute_tangents() during asset preparation, before the mesh is handed to the renderer
- Regenerate the mesh from source data if extraction already happened
Example fix
// before let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::RENDER_WORLD); // ...extracted... mesh.compute_tangents(); // Err(MeshAccessError::ExtractedToRenderWorld) // after let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default()); mesh.compute_tangents().unwrap();
Defensive patterns
Strategy: validation
Validate before calling
if mesh.asset_usage().contains(RenderAssetUsages::MAIN_WORLD) {
mesh.compute_tangents()?;
} else {
// recreate mesh with RenderAssetUsages::default() first
} Try / catch
if let Err(GenerateTangentsError::MeshAccessError(MeshAccessError::ExtractedToRenderWorld)) =
mesh.compute_tangents()
{
// re-run generation on a fresh CPU-resident mesh
} Prevention
- compute_tangents is CPU work: do it before extraction, on MAIN_WORLD-readable meshes
- Reserve RenderAssetUsages::RENDER_WORLD for meshes past all processing
- Schedule tangent baking in asset-preparation systems that run before rendering
When it happens
Trigger: Calling mesh.compute_tangents() on a Mesh created with RenderAssetUsages::RENDER_WORLD after it has been prepared by the render pipeline at least once.
Common situations: Memory-tight projects marking generated meshes render-world-only; systems that add normal maps and re-tangent meshes at runtime, running after the first frame has already extracted the asset.
Related errors
- Mesh access error: {0}
- failed to generate tangents: {0}
- cannot generate tangents for {0:?}
- missing indices
- missing vertex attributes '{0}'
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/4b3f3a35a39753a3.
Report an issue: GitHub.