{"record":{"id":"73268ad964b9978f","repo":"bevyengine/bevy","slug":"incompatible-vertex-attribute-types-and","errorCode":null,"errorMessage":"Incompatible vertex attribute types: {} and {}","messagePattern":"Incompatible vertex attribute types: (.+?) and (.+?)","errorType":"exception","errorClass":"MeshMergeError","httpStatus":null,"severity":"error","filePath":"crates/bevy_mesh/src/mesh.rs","lineNumber":3025,"sourceCode":"            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    )]\n    IncompatiblePrimitiveTopology {\n        self_primitive_topology: PrimitiveTopology,\n        other_primitive_topology: PrimitiveTopology,\n    },\n    #[error(\"Mesh access error: {0}\")]\n    MeshAccessError(#[from] MeshAccessError),\n}\n\n#[cfg(test)]","sourceCodeStart":3007,"sourceCodeEnd":3043,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_mesh/src/mesh.rs#L3007-L3043","documentation":"MeshMergeError::IncompatibleVertexAttributes (crates/bevy_mesh/src/mesh.rs:3025), returned by Mesh::merge. When both meshes carry an attribute with the same id, merge extends self's buffer with other's; that only works when the VertexAttributeValues variants match exactly (Float32x3 with Float32x3, etc.). A type mismatch is rejected because concatenating different byte layouts would corrupt the buffer.","triggerScenarios":"Calling mesh_a.merge(&mesh_b) where an attribute with the same MeshVertexAttributeId exists in both but with different formats — e.g. ATTRIBUTE_POSITION as Float32x3 in one and Float32x2 in the other, or joint indices as Uint16x4 vs Uint32x4. Checked per attribute during the extend loop (mesh.rs:2182).","commonSituations":"Merging geometry from different sources (a Bevy primitive plus an imported glTF mesh); one side passed through compression/packing (Snorm8x4 normals) while the other kept plain Float32x3; custom attributes registered under the same id with inconsistent formats across code versions.","solutions":["Convert the mismatched attribute in one mesh so both use the same VertexAttributeValues variant, then merge again","Remove the attribute you do not need from one mesh with mesh.remove_attribute(id) before merging","Regenerate one mesh through the same builder/pipeline as the other so attribute formats line up by construction"],"exampleFix":"// before: same attribute id, different formats\nlet mut a = plane_mesh(); // POSITION: Float32x3\nlet mut b = imported_mesh(); // POSITION: Float32x2\na.merge(&b); // Err(IncompatibleVertexAttributes { self_attribute: POSITION(Float32x3), other: Float32x2 })\n\n// after: convert b's positions to Float32x3 first\nlet fixed: Vec<[f32; 3]> = b.attribute(Mesh::ATTRIBUTE_POSITION).unwrap().as_float2().unwrap().iter().map(|p| [p[0], p[1], 0.0]).collect();\nb.insert_attribute(Mesh::ATTRIBUTE_POSITION, fixed);\na.merge(&b).unwrap();","handlingStrategy":"try-catch","validationCode":"use std::mem::discriminant;\nuse bevy_mesh::MeshVertexAttributeId;\n\n// true when every attribute shared by both meshes uses the same values variant\nfn attributes_compatible(a: &Mesh, b: &Mesh) -> bool {\n    a.attributes().all(|(attr, va)| {\n        b.attribute(attr.id).map_or(true, |vb| {\n            discriminant(va) == discriminant(vb)\n        })\n    })\n}","typeGuard":null,"tryCatchPattern":"match a.merge(&b) {\n    Ok(()) => {}\n    Err(MeshMergeError::IncompatibleVertexAttributes { self_attribute, other_attribute }) => {\n        bevy::log::error!(\n            \"cannot merge: {} vs {:?}\", self_attribute.name, other_attribute.map(|a| a.name)\n        );\n        // convert or remove the offending attribute, then retry once\n    }\n    Err(e) => bevy::log::error!(\"merge failed: {e}\"),\n}","preventionTips":["Merged meshes should come from the same builder/pipeline so formats match by construction","Compare VertexAttributeValues discriminants for shared attribute ids before merging","Apply vertex compression only after all merges are done"],"tags":["bevy","mesh","merge","vertex-attribute","format-mismatch"],"backgroundTag":"mesh-merge-incompatible","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"}