{"record":{"id":"e3576acaed060eeb","repo":"bevyengine/bevy","slug":"missing-indices","errorCode":null,"errorMessage":"missing indices","messagePattern":"missing indices","errorType":"exception","errorClass":"GenerateTangentsError","httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/mikktspace.rs","lineNumber":67,"sourceCode":"    }\n\n    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    };","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/mikktspace.rs#L49-L85","documentation":"GenerateTangentsError::MissingIndices (crates/bevy_mesh/src/mikktspace.rs:67), returned when Mesh::compute_tangents is called on a mesh without an index buffer. Mikktspace needs face connectivity (which vertices form each triangle) to compute per-triangle tangents; raw vertex soups carry no such information.","triggerScenarios":"Calling compute_tangents() on a mesh built with only insert_attribute calls and no insert_indices / with_inserted_indices — e.g. a manually assembled triangle soup, or a mesh processed by duplicate_vertices() (which strips indices).","commonSituations":"Following the flat-normals recipe (duplicate_vertices -> compute_flat_normals) and then adding normal mapping; hand-written quad/triangle builders that rely on implicit ordering; importer paths that drop empty index buffers.","solutions":["Generate an index buffer with mesh.merge_duplicate_vertices() (it welds the soup and produces Indices::U32)","Or supply explicit triangle indices with mesh.insert_indices(Indices::U32(vec)) / Indices::U16","Re-check ordering: compute tangents after indexing, not before"],"exampleFix":"// before: attribute-only mesh\nlet mut mesh = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());\nmesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions);\nmesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals);\nmesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs);\nmesh.compute_tangents(); // Err(MissingIndices)\n\n// after: weld into an indexed mesh first\nmesh.merge_duplicate_vertices().unwrap();\nmesh.compute_tangents().unwrap();","handlingStrategy":"try-catch","validationCode":"if mesh.indices().is_none() {\n    mesh.merge_duplicate_vertices()?; // produces Indices::U32\n}\nmesh.compute_tangents()?;","typeGuard":"fn is_indexed(mesh: &Mesh) -> bool {\n    mesh.indices().is_some()\n}","tryCatchPattern":"match mesh.compute_tangents() {\n    Ok(()) => {}\n    Err(GenerateTangentsError::MissingIndices) => {\n        mesh.merge_duplicate_vertices().expect(\"weld failed\");\n        mesh.compute_tangents()?; // retry once, now indexed\n    }\n    Err(e) => bevy::log::error!(\"tangent generation failed: {e}\"),\n}","preventionTips":["Index your meshes before compute_tangents — merge_duplicate_vertices is the cheapest route for soups","Note duplicate_vertices() strips indices; re-index afterwards","Order pipeline: attributes -> indices -> normals -> tangents"],"tags":["bevy","mesh","tangents","mikktspace","indices","missing-data"],"backgroundTag":"missing-index-buffer","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"}