{"record":{"id":"6aa24baf5458ec72","repo":"bevyengine/bevy","slug":"indices-weren-t-in-chunks-according-to-topology","errorCode":null,"errorMessage":"Indices weren't in chunks according to topology","messagePattern":"Indices weren't in chunks according to topology","errorType":"exception","errorClass":"MeshWindingInvertError","httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/index.rs","lineNumber":59,"sourceCode":"            FourIterators::First(iter) => iter.size_hint(),\n            FourIterators::Second(iter) => iter.size_hint(),\n            FourIterators::Third(iter) => iter.size_hint(),\n            FourIterators::Fourth(iter) => iter.size_hint(),\n        }\n    }\n}\n\n/// An error that occurred while trying to invert the winding of a [`Mesh`](super::Mesh).\n#[derive(Debug, Error)]\npub enum MeshWindingInvertError {\n    /// This error occurs when you try to invert the winding for a mesh with [`PrimitiveTopology::PointList`](super::PrimitiveTopology::PointList).\n    #[error(\"Mesh winding inversion does not work for primitive topology `PointList`\")]\n    WrongTopology,\n\n    /// This error occurs when you try to invert the winding for a mesh with\n    /// * [`PrimitiveTopology::TriangleList`](super::PrimitiveTopology::TriangleList), but the indices are not in chunks of 3.\n    /// * [`PrimitiveTopology::LineList`](super::PrimitiveTopology::LineList), but the indices are not in chunks of 2.\n    #[error(\"Indices weren't in chunks according to topology\")]\n    AbruptIndicesEnd,\n    #[error(\"Mesh access error: {0}\")]\n    MeshAccessError(#[from] MeshAccessError),\n}\n\n/// An error that occurred while trying to extract a collection of triangles from a [`Mesh`](super::Mesh).\n#[derive(Debug, Error)]\npub enum MeshTrianglesError {\n    #[error(\"Source mesh does not have primitive topology TriangleList or TriangleStrip\")]\n    WrongTopology,\n\n    #[error(\"Source mesh position data is not Float32x3\")]\n    PositionsFormat,\n\n    #[error(\"Face index data references vertices that do not exist\")]\n    BadIndices,\n    #[error(\"mesh access error: {0}\")]\n    MeshAccessError(#[from] MeshAccessError),","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/index.rs#L41-L77","documentation":"When inverting winding, TriangleList index data is reordered in chunks of 3 and LineList in chunks of 2. If the index buffer length is not an exact multiple of the chunk size, the trailing partial chunk cannot form a complete face, and MeshWindingInvertError::AbruptIndicesEnd is returned instead of corrupting the buffer.","triggerScenarios":"mesh.invert_winding() where the Indices buffer length modulo 3 is nonzero for a TriangleList mesh, or modulo 2 nonzero for a LineList mesh.","commonSituations":"Hand-built index buffers missing one index; code that pushes or removes single indices while editing a mesh; truncated or partially downloaded imported meshes.","solutions":["Validate that the index count divides evenly by 3 (TriangleList) or 2 (LineList) before calling invert_winding","Repair the index buffer so every face is complete: drop or complete the partial chunk","Use slice::as_chunks when building the buffer to detect partial chunks early"],"exampleFix":"// before\nmesh.invert_winding()?; // Err(AbruptIndicesEnd) when index count % 3 != 0\n\n// after\nlet index_len = mesh.indices().map(|i| match i {\n    Indices::U16(v) => v.len(),\n    Indices::U32(v) => v.len(),\n});\nlet chunk = match mesh.primitive_topology() {\n    PrimitiveTopology::TriangleList => 3,\n    PrimitiveTopology::LineList => 2,\n    _ => 1,\n};\nif index_len.is_some_and(|len| len % chunk == 0) {\n    mesh.invert_winding()?;\n}","handlingStrategy":"validation","validationCode":"fn indices_chunked(mesh: &Mesh) -> bool {\n    let Some(indices) = mesh.indices() else { return true; };\n    let len = match indices {\n        Indices::U16(v) => v.len(),\n        Indices::U32(v) => v.len(),\n    };\n    match mesh.primitive_topology() {\n        PrimitiveTopology::TriangleList => len % 3 == 0,\n        PrimitiveTopology::LineList => len % 2 == 0,\n        _ => true,\n    }\n}","typeGuard":null,"tryCatchPattern":"match mesh.invert_winding() {\n    Ok(()) => {}\n    Err(MeshWindingInvertError::AbruptIndicesEnd) => { /* repair the index buffer, then retry once */ }\n    Err(other) => { /* handle topology/access errors */ }\n}","preventionTips":["Build index buffers with as_chunks or array chunks so partial faces are impossible","Re-validate index counts after every edit that pushes or removes indices","Log index buffer lengths at import time to catch truncated assets"],"tags":["bevy","bevy-mesh","rust","mesh","indices","winding","validation"],"backgroundTag":"mesh-index-count-mismatch","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}