bevyengine/bevy · error · MeshMergeError
Incompatible primitive topologies: {:?} and {:?}
Error message
Incompatible primitive topologies: {:?} and {:?} What it means
MeshMergeError::IncompatiblePrimitiveTopology (crates/bevy_mesh/src/mesh.rs:3030), returned by Mesh::merge as its very first check (mesh.rs:2135). Merging concatenates index buffers with an offset, which is only meaningful when both meshes interpret those indices under the same primitive topology; mixing e.g. TriangleList with TriangleStrip would produce garbage geometry, so it is rejected up front.
Source
Thrown at crates/bevy_mesh/src/mesh.rs:3030
/// Error that can occur when calling [`Mesh::merge_duplicate_vertices`]
#[derive(Error, Debug, Clone)]
pub enum MeshMergeDuplicateVerticesError {
#[error("Index attribute already set.")]
IndicesAlreadySet,
#[error("Mesh access error: {0}")]
MeshAccessError(#[from] MeshAccessError),
}
/// Error that can occur when calling [`Mesh::merge`].
#[derive(Error, Debug, Clone)]
pub enum MeshMergeError {
#[error("Incompatible vertex attribute types: {} and {}", self_attribute.name, other_attribute.map(|a| a.name).unwrap_or("None"))]
IncompatibleVertexAttributes {
self_attribute: MeshVertexAttribute,
other_attribute: Option<MeshVertexAttribute>,
},
#[error(
"Incompatible primitive topologies: {:?} and {:?}",
self_primitive_topology,
other_primitive_topology
)]
IncompatiblePrimitiveTopology {
self_primitive_topology: PrimitiveTopology,
other_primitive_topology: PrimitiveTopology,
},
#[error("Mesh access error: {0}")]
MeshAccessError(#[from] MeshAccessError),
}
#[cfg(test)]
mod tests {
use super::Mesh;
#[cfg(feature = "serialize")]
use super::SerializedMesh;
use crate::mesh::{Indices, MeshWindingInvertError, VertexAttributeValues};View on GitHub (pinned to 396ca72708)
Solutions
- Rebuild one mesh with the same PrimitiveTopology you pass to Mesh::new for the other
- Convert the strip mesh's triangle list (re-expand strip indices into triangles) before merging
- Batch by topology: group meshes into merge sets that share a topology instead of merging across groups
Example fix
// before
let mut a = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());
let b = Mesh::new(PrimitiveTopology::TriangleStrip, RenderAssetUsages::default());
a.merge(&b); // Err(IncompatiblePrimitiveTopology { self: TriangleList, other: TriangleStrip })
// after: build both with the same topology
let b = Mesh::new(PrimitiveTopology::TriangleList, RenderAssetUsages::default());
a.merge(&b).unwrap(); Defensive patterns
Strategy: validation
Validate before calling
fn same_topology(a: &Mesh, b: &Mesh) -> bool {
a.primitive_topology() == b.primitive_topology()
}
if same_topology(&mesh_a, &mesh_b) {
mesh_a.merge(&mesh_b)?;
} Type guard
fn mergeable_pair<'a>(a: &'a mut Mesh, b: &'a Mesh) -> Option<&'a mut Mesh> {
(a.primitive_topology() == b.primitive_topology()).then_some(a)
} Try / catch
if let Err(MeshMergeError::IncompatiblePrimitiveTopology {
self_primitive_topology,
other_primitive_topology,
}) = mesh_a.merge(&mesh_b)
{
bevy::log::error!("topology mismatch: {self_primitive_topology:?} vs {other_primitive_topology:?}");
} Prevention
- Set topology once in a shared factory for all meshes that will be batched together
- Group merge candidates by PrimitiveTopology before merging
- Beware TriangleStrip leftovers when porting older mesh code
When it happens
Trigger: Calling mesh_a.merge(&mesh_b) where mesh_a was created with PrimitiveTopology::TriangleList and mesh_b with PrimitiveTopology::TriangleStrip (or any other differing variant such as LineList vs LineStrip).
Common situations: Merging a Bevy primitive (always TriangleList) with a custom mesh built as TriangleStrip to save indices; mixing 2D line geometry (LineList) with triangle meshes in a batching pass; topology defaults changing between asset importer versions.
Related errors
- cannot generate tangents for {0:?}
- Meshes used with Extrusions must have a primitive topology o
- unsupported primitive mode
- Incompatible vertex attribute types: {} and {}
- Mismatched vertex attribute values
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/56f98019016600d8.
Report an issue: GitHub.