{"record":{"id":"a4bbbd765a54af4a","repo":"bevyengine/bevy","slug":"unsupported-primitive-mode","errorCode":null,"errorMessage":"unsupported primitive mode","messagePattern":"unsupported primitive mode","errorType":"exception","errorClass":"GltfError","httpStatus":null,"severity":"error","filePath":"crates/bevy_gltf/src/loader/mod.rs","lineNumber":87,"sourceCode":"        material::{\n            alpha_mode, material_label, needs_tangents, uv_channel,\n            warn_on_differing_texture_transforms,\n        },\n        mesh::{primitive_name, primitive_topology},\n        scene::{node_name, node_transform},\n        texture::{texture_sampler, texture_transform_to_affine2},\n    },\n};\nuse crate::convert_coordinates::GltfConvertCoordinates;\n\n/// Must match [`MAX_JOINTS`](https://docs.rs/bevy/latest/bevy/pbr/constant.MAX_JOINTS.html)\npub const MAX_JOINTS: usize = 256;\n\n/// An error that occurs when loading a glTF file.\n#[derive(Error, Debug)]\npub enum GltfError {\n    /// Unsupported primitive mode.\n    #[error(\"unsupported primitive mode\")]\n    UnsupportedPrimitive {\n        /// The primitive mode.\n        mode: Mode,\n    },\n    /// Invalid glTF file.\n    #[error(\"invalid glTF file: {0}\")]\n    Gltf(#[from] gltf::Error),\n    /// Binary blob is missing.\n    #[error(\"binary blob is missing\")]\n    MissingBlob,\n    /// Decoding the base64 mesh data failed.\n    #[error(\"failed to decode base64 mesh data\")]\n    Base64Decode(#[from] base64::DecodeError),\n    /// Unsupported buffer format.\n    #[error(\"unsupported buffer format\")]\n    BufferFormatUnsupported,\n    /// The buffer URI was unable to be resolved with respect to the asset path.\n    #[error(\"invalid buffer uri: {0}. asset path error={1}\")]","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_gltf/src/loader/mod.rs#L69-L105","documentation":"Bevy's GltfLoader only maps five of glTF's eight primitive modes to a wgpu PrimitiveTopology: Points, Lines, LineStrip, Triangles, TriangleStrip (crates/bevy_gltf/src/loader/gltf_ext/mesh.rs:21-29). Loading a mesh primitive that uses Mode::LineLoop (mode 2) or Mode::TriangleFan (mode 6) returns UnsupportedPrimitive { mode } from primitive_topology(), called during primitive loading at loader/mod.rs:766. A triangle fan is always expressible as a triangle list by rewiring the index buffer, so this is a data problem, not a Bevy limitation in principle.","triggerScenarios":"A .gltf/.glb whose mesh primitive JSON contains \"mode\": 2 (LINE_LOOP) or \"mode\": 6 (TRIANGLE_FAN); any file loaded via asset_server.load(...gltf) or GltfLoader::load that reaches primitive_topology(primitive.mode()) and matches the catch-all arm.","commonSituations":"Legacy CAD/DCC exporters (old 3ds Max, some FBX-to-glTF converters, assimp with fan preservation), hand-authored glTF JSON, or models converted from OpenGL-era tutorials that used GL_TRIANGLE_FAN/GL_LINE_LOOP.","solutions":["Re-export the model from your DCC with a glTF 2.0 exporter (Blender's glTF exporter triangulates fans/loops into lists/strips by default).","If you control the pipeline, preprocess the file: rewrite TRIANGLE_FAN indices into TRIANGLE_LIST order and set \"mode\": 4.","If the geometry is decorative, strip the offending primitive or convert the mesh to lines/points in a 3D tool.","As a last resort, implement a custom loader (fork or GltfLoader extension) that performs the fan-to-list conversion."],"exampleFix":"// scene.gltf (before)\n\"primitives\": [{ \"mode\": 6, \"indices\": 0 }]  // TRIANGLE_FAN\n// after: fan converted to list by the exporter\n\"primitives\": [{ \"mode\": 4, \"indices\": 1 }]  // TRIANGLES","handlingStrategy":"validation","validationCode":"fn has_unsupported_primitives(path: &std::path::Path) -> bool {\n    let (doc, _blob, _) = gltf::import(path).unwrap();\n    doc.meshes()\n        .flat_map(|m| m.primitives())\n        .any(|p| !is_supported_mode(p.mode()))\n}","typeGuard":"fn is_supported_mode(mode: gltf::mesh::Mode) -> bool {\n    use gltf::mesh::Mode::*;\n    matches!(mode, Points | Lines | LineStrip | Triangles | TriangleStrip)\n}","tryCatchPattern":"match err {\n    GltfError::UnsupportedPrimitive { mode } => {\n        warn!(\"skipping mesh primitive, glTF mode {mode:?} not supported\");\n    }\n    other => return Err(other.into()),\n}","preventionTips":["Run gltf-validator on every asset before adding it to the project.","Export through a mainstream glTF 2.0 exporter which emits lists/strips only.","In CI, fail builds containing meshes with mode 2 or 6."],"tags":["gltf","bevy","mesh","primitive-topology","triangle-fan"],"backgroundTag":"unsupported-mesh-topology","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"}