{"record":{"id":"26fd61a39108fc65","repo":"bevyengine/bevy","slug":"index-attribute-already-set","errorCode":null,"errorMessage":"Index attribute already set.","messagePattern":"Index attribute already set\\.","errorType":"exception","errorClass":"MeshMergeDuplicateVerticesError","httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/mesh.rs","lineNumber":3016,"sourceCode":"                        warn!(\n                            \"Deserialized mesh contains custom vertex attribute {attribute:?} that \\\n                            was not specified with `MeshDeserializer::add_custom_vertex_attribute`. Ignoring.\"\n                        );\n                        return None;\n                    };\n                    Some((id, data))\n                })\n                .collect()),\n            indices: serialized_mesh.indices.into(),\n            ..Mesh::new(serialized_mesh.primitive_topology, RenderAssetUsages::default())\n        }\n    }\n}\n\n/// Error that can occur when calling [`Mesh::merge_duplicate_vertices`]\n#[derive(Error, Debug, Clone)]\npub enum MeshMergeDuplicateVerticesError {\n    #[error(\"Index attribute already set.\")]\n    IndicesAlreadySet,\n    #[error(\"Mesh access error: {0}\")]\n    MeshAccessError(#[from] MeshAccessError),\n}\n\n/// Error that can occur when calling [`Mesh::merge`].\n#[derive(Error, Debug, Clone)]\npub enum MeshMergeError {\n    #[error(\"Incompatible vertex attribute types: {} and {}\", self_attribute.name, other_attribute.map(|a| a.name).unwrap_or(\"None\"))]\n    IncompatibleVertexAttributes {\n        self_attribute: MeshVertexAttribute,\n        other_attribute: Option<MeshVertexAttribute>,\n    },\n    #[error(\n        \"Incompatible primitive topologies: {:?} and {:?}\",\n        self_primitive_topology,\n        other_primitive_topology\n    )]","sourceCodeStart":2998,"sourceCodeEnd":3034,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/mesh.rs#L2998-L3034","documentation":"MeshMergeDuplicateVerticesError::IndicesAlreadySet (crates/bevy_mesh/src/mesh.rs:3016), returned by Mesh::merge_duplicate_vertices when self.try_indices() finds an existing index buffer. The function's contract is to CREATE indices from a non-indexed vertex soup; an already-indexed mesh violates that precondition, so it refuses instead of overwriting valid topology.","triggerScenarios":"Calling merge_duplicate_vertices() on any mesh that already has indices set: meshes from Bevy primitive builders (Sphere, Torus, ... all insert Indices::U32/U16), imported glTF geometry (indexed by nature), or a mesh where you previously called insert_indices/with_inserted_indices or an earlier successful merge_duplicate_vertices.","commonSituations":"Developer welds an imported indexed mesh to smooth seams and calls merge_duplicate_vertices directly; mixing up the documented normal-generation recipes (compute_smooth_normals wants indexed geometry, compute_flat_normals wants non-indexed) and reaching for the wrong helper.","solutions":["If you really want to rebuild indices, drop the existing buffer first: mesh.remove_indices(), then merge_duplicate_vertices()","For flat shading of indexed geometry use the documented recipe: mesh.duplicate_vertices() then mesh.compute_flat_normals()","For smooth shading keep the existing indices and call compute_smooth_normals() instead"],"exampleFix":"// before: Sphere builder already inserted indices\nlet mut mesh = Sphere::new(1.0).mesh().build();\nmesh.merge_duplicate_vertices(); // Err(IndicesAlreadySet)\n\n// after: drop old indices, then dedupe\nlet mut mesh = Sphere::new(1.0).mesh().build();\nmesh.remove_indices();\nmesh.merge_duplicate_vertices().unwrap();","handlingStrategy":"try-catch","validationCode":"if mesh.indices().is_none() {\n    mesh.merge_duplicate_vertices()?;\n} else {\n    // already indexed: nothing to dedupe, or remove_indices() first if rebuilding\n}","typeGuard":"fn is_unindexed(mesh: &Mesh) -> bool {\n    mesh.indices().is_none()\n}","tryCatchPattern":"match mesh.merge_duplicate_vertices() {\n    Ok(()) => {}\n    Err(MeshMergeDuplicateVerticesError::IndicesAlreadySet) => {\n        // decide: keep existing topology, or mesh.remove_indices() and retry\n    }\n    Err(MeshMergeDuplicateVerticesError::MeshAccessError(e)) => {\n        bevy::log::error!(\"mesh data unavailable: {e}\");\n    }\n}","preventionTips":["Remember merge_duplicate_vertices is for NON-indexed meshes only","Gate the call behind mesh.indices().is_none()","Keep the documented recipes straight: smooth normals need indices, flat normals need duplicate_vertices"],"tags":["bevy","mesh","indices","merge-duplicate-vertices","precondition"],"backgroundTag":"invalid-mesh-state","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"}