{"record":{"id":"44b7b2b78567fb2f","repo":"bevyengine/bevy","slug":"failed-to-generate-tangents-0","errorCode":null,"errorMessage":"failed to generate tangents: {0}","messagePattern":"failed to generate tangents: (.+?)","errorType":"exception","errorClass":"GltfError","httpStatus":null,"severity":"error","filePath":"crates/bevy_gltf/src/loader/mod.rs","lineNumber":128,"sourceCode":"    InvalidImageMimeType(String),\n    /// Error when loading a texture. Might be due to a disabled image file format feature.\n    #[error(\"You may need to add the feature for the file format: {0}\")]\n    ImageError(#[from] TextureError),\n    /// The image URI was unable to be resolved with respect to the asset path.\n    #[error(\"invalid image uri: {0}. asset path error={1}\")]\n    InvalidImageUri(String, ParseAssetPathError),\n    /// Failed to read bytes from an asset path.\n    #[error(\"failed to read bytes from an asset path: {0}\")]\n    ReadAssetBytesError(#[from] ReadAssetBytesError),\n    /// Failed to load asset from an asset path.\n    #[error(\"failed to load asset from an asset path: {0}\")]\n    AssetLoadError(#[from] AssetLoadError),\n    /// Missing sampler for an animation.\n    #[error(\"Missing sampler for animation {0}\")]\n    #[from(ignore)]\n    MissingAnimationSampler(usize),\n    /// Failed to generate tangents.\n    #[error(\"failed to generate tangents: {0}\")]\n    GenerateTangentsError(#[from] bevy_mesh::GenerateTangentsError),\n    /// Failed to generate morph targets.\n    #[error(\"failed to generate morph targets: {0}\")]\n    MorphTarget(#[from] bevy_mesh::morph::MorphBuildError),\n    /// Circular children in Nodes\n    #[error(\"GLTF model must be a tree, found cycle instead at node indices: {0:?}\")]\n    #[from(ignore)]\n    CircularChildren(String),\n    /// Failed to load a file.\n    #[error(\"failed to load file: {0}\")]\n    Io(#[from] Error),\n}\n\n/// Loads glTF files with all of their data as their corresponding bevy representations.\n#[derive(TypePath)]\npub struct GltfLoader {\n    /// List of compressed image formats handled by the loader.\n    pub supported_compressed_formats: CompressedImageFormats,","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_gltf/src/loader/mod.rs#L110-L146","documentation":"GltfError::GenerateTangentsError (#[from] bevy_mesh::GenerateTangentsError) wraps the failure of mesh.generate_tangents() at loader/mod.rs:862. The loader computes tangents for triangle-list meshes that lack a TANGENT attribute but need them (normal-mapped materials); generation requires positions, normals, UVs and a triangle index list, and fails on missing attributes, degenerate/zero-area triangles, or too few vertices.","triggerScenarios":"A primitive with a normal-map texture but no TANGENT accessor, where the mesh also lacks UV or NORMAL attributes (or indices); meshes containing degenerate triangles that break mikktspace-style winding tests.","commonSituations":"Exporters with 'export UVs/normals' disabled; decimated or LOD meshes; CAD tessellations with slivers; flat-colored models given a normal-mapped material after the fact.","solutions":["Re-export with UVs, normals and tangents (Blender: enable 'Export Tangents').","Or ensure the mesh has POSITION + NORMAL + TEXCOORD_0 and valid triangle indices so generation succeeds.","Remove the normal map from the material if tangents are unavailable.","Clean degenerate triangles in a DCC (merge by distance / custom normals tools)."],"exampleFix":"// Blender glTF export options (before)\n// [ ] Export Tangents, UVs off\n// (after)\n// [x] Export Tangents and UV Coordinates, geometry = triangles","handlingStrategy":"validation","validationCode":"fn tangent_generation_safe(doc: &gltf::Document) -> bool {\n    doc.meshes().flat_map(|m| m.primitives()).all(|p| {\n        let sems: Vec<_> = p.attributes().iter().map(|(s, _)| s).collect();\n        let needs_tangents = p.material().normal_texture().is_some();\n        !needs_tangents\n            || sems.contains(&gltf::Semantic::Tangents)\n            || (sems.contains(&gltf::Semantic::Positions)\n                && sems.contains(&gltf::Semantic::Normals)\n                && sems.contains(&gltf::Semantic::TexCoords(0))\n                && p.indices().is_some())\n    })\n}","typeGuard":null,"tryCatchPattern":"match err {\n    GltfError::GenerateTangentsError(e) => {\n        warn!(\"tangent generation failed ({e:?}); re-export with UVs+normals or without normal map\");\n    }\n    other => return Err(other.into()),\n}","preventionTips":["Always export UVs and normals for normal-mapped meshes.","Prefer exporting tangents directly (Blender 'Export Tangents').","Remove normal maps from meshes lacking UV data."],"tags":["gltf","tangents","mesh","normal-mapping","bevy"],"backgroundTag":"tangent-generation-failed","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"}