{"record":{"id":"4f0b789420474d39","repo":"bevyengine/bevy","slug":"missing-vertex-attributes-0","errorCode":null,"errorMessage":"missing vertex attributes '{0}'","messagePattern":"missing vertex attributes '(.+?)'","errorType":"exception","errorClass":"GenerateTangentsError","httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/mikktspace.rs","lineNumber":69,"sourceCode":"    fn set_tangent(\n        &mut self,\n        tangent_space: Option<bevy_mikktspace::TangentSpace>,\n        face: usize,\n        vert: usize,\n    ) {\n        let idx = self.index(face, vert);\n        self.tangents[idx] = tangent_space.unwrap_or_default().tangent_encoded();\n    }\n}\n\n#[derive(Error, Debug)]\n/// Failed to generate tangents for the mesh.\npub enum GenerateTangentsError {\n    #[error(\"cannot generate tangents for {0:?}\")]\n    UnsupportedTopology(PrimitiveTopology),\n    #[error(\"missing indices\")]\n    MissingIndices,\n    #[error(\"missing vertex attributes '{0}'\")]\n    MissingVertexAttribute(&'static str),\n    #[error(\"the '{0}' vertex attribute should have {1:?} format\")]\n    InvalidVertexAttributeFormat(&'static str, VertexFormat),\n    #[error(\"mesh not suitable for tangent generation\")]\n    MikktspaceError(#[from] bevy_mikktspace::GenerateTangentSpaceError),\n    #[error(\"Mesh access error: {0}\")]\n    MeshAccessError(#[from] MeshAccessError),\n}\n\npub(crate) fn generate_tangents_for_mesh(\n    mesh: &Mesh,\n) -> Result<Vec<[f32; 4]>, GenerateTangentsError> {\n    match mesh.primitive_topology() {\n        PrimitiveTopology::TriangleList => {}\n        other => return Err(GenerateTangentsError::UnsupportedTopology(other)),\n    };\n\n    let positions = mesh.try_attribute_option(Mesh::ATTRIBUTE_POSITION)?.ok_or(","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/mikktspace.rs#L51-L87","documentation":"GenerateTangentsError::MissingVertexAttribute (crates/bevy_mesh/src/mikktspace.rs:69), returned by Mesh::compute_tangents when one of the three required attributes is absent. Tangent generation reads Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_NORMAL and Mesh::ATTRIBUTE_UV_0 (mikktspace.rs:88/97/106); the error carries the missing attribute's name so you know exactly which one to add.","triggerScenarios":"Calling compute_tangents() on a mesh that has positions and indices but no ATTRIBUTE_NORMAL (normals not yet computed), or no ATTRIBUTE_UV_0 (UVs never authored or stripped by compression).","commonSituations":"Procedural meshes where the developer forgot normals before adding a normal map; imported assets whose UV set 0 was dropped; pipeline ordering bugs where tangents are computed before compute_smooth_normals has run.","solutions":["Compute normals first: mesh.compute_smooth_normals() (indexed) or duplicate_vertices()+compute_flat_normals()","Author UVs: mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs) with one Vec2 per vertex","Inspect the error payload — the '{0}' field names the exact missing attribute"],"exampleFix":"// before\nmesh.compute_tangents(); // Err(MissingVertexAttribute(\"Vertex_Normal\"))\n\n// after: satisfy all three prerequisites\nmesh.compute_smooth_normals().unwrap(); // adds ATTRIBUTE_NORMAL\nmesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs); // adds UV_0\nmesh.compute_tangents().unwrap();","handlingStrategy":"validation","validationCode":"fn has_tangent_inputs(mesh: &Mesh) -> bool {\n    mesh.attribute(Mesh::ATTRIBUTE_POSITION).is_some()\n        && mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_some()\n        && mesh.attribute(Mesh::ATTRIBUTE_UV_0).is_some()\n}\n\nif has_tangent_inputs(&mesh) {\n    mesh.compute_tangents()?;\n}","typeGuard":"fn tangent_ready(mesh: &Mesh) -> bool {\n    matches!(mesh.primitive_topology(), PrimitiveTopology::TriangleList)\n        && mesh.indices().is_some()\n        && mesh.attribute(Mesh::ATTRIBUTE_POSITION).is_some()\n        && mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_some()\n        && mesh.attribute(Mesh::ATTRIBUTE_UV_0).is_some()\n}","tryCatchPattern":"if let Err(GenerateTangentsError::MissingVertexAttribute(name)) = mesh.compute_tangents() {\n    bevy::log::error!(\"missing '{name}' before compute_tangents\");\n}","preventionTips":["compute_tangents needs POSITION + NORMAL + UV_0 — compute normals first","Author or import a UV set before enabling normal maps","Use the error payload's attribute name to point at the exact gap"],"tags":["bevy","mesh","tangents","mikktspace","vertex-attribute","missing-data"],"backgroundTag":"missing-vertex-attribute","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"}