bevyengine/bevy · error · MeshAttributeError
Missing attribute "{0}"
Error message
Missing attribute "{0}" What it means
MeshAttributeError::MissingAttribute is returned by the expect_attribute_* helpers in bevy_mesh::skinning when a mesh lacks an attribute that was expected with a specific format. It surfaces mainly through SkinnedMeshBounds::from_mesh and InfluenceIterator::new, which require Mesh::ATTRIBUTE_POSITION (Float32x3), Mesh::ATTRIBUTE_JOINT_INDEX (Uint16x4) and Mesh::ATTRIBUTE_JOINT_WEIGHT (Float32x4). The message names the missing attribute.
Source
Thrown at crates/bevy_mesh/src/skinning.rs:414
self.influence_index += 1;
if joint_weight > 0.0 {
return Some(Influence {
vertex_index: self.vertex_index,
joint_index: JointIndex(joint_index),
joint_weight,
});
}
}
}
}
/// Generic error for when a mesh was expected to have a certain attribute with
/// a certain format.
#[derive(Copy, Clone, PartialEq, Debug, Error)]
pub enum MeshAttributeError {
#[error("Missing attribute \"{0}\"")]
MissingAttribute(&'static str),
#[error("Attribute \"{0}\" has unexpected format {1:?}")]
UnexpectedFormat(&'static str, VertexFormat),
}
// Implements a function that returns a mesh attribute's data or `MeshAttributeError`.
//
// ```
// impl_expect_attribute!(expect_attribute_float32x3, Float32x3, [f32; 3]);
//
// let positions: Vec<[f32; 3]> = expect_attribute_float32x3(mesh, Mesh::ATTRIBUTE_POSITION)?;
// ```
macro_rules! impl_expect_attribute {
($name:ident, $value_type:ident, $output_type:ty) => {
fn $name<'a>(
mesh: &'a Mesh,
attribute: MeshVertexAttribute,
) -> Result<&'a Vec<$output_type>, MeshAttributeError> {View on GitHub (pinned to 396ca72708)
Solutions
- Insert the missing skin attributes in the exact expected formats: JOINT_INDEX as VertexAttributeValues::Uint16x4 and JOINT_WEIGHT as VertexAttributeValues::Float32x4 (plus POSITION as Float32x3)
- Guard the call: only derive SkinnedMeshBounds for meshes that actually carry skin attributes (check mesh.attribute(Mesh::ATTRIBUTE_JOINT_INDEX).is_some())
- If the mesh is supposed to be static, skip from_mesh entirely and use mesh.compute_aabb()
- Inspect the error's attribute name to see exactly which of the three attributes is absent
Example fix
// before: mesh without skin data
let bounds = SkinnedMeshBounds::from_mesh(&mesh)?; // Err(MissingAttribute("JOINT_INDEX"))
// after: provide the required attributes
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, positions); // Vec<[f32; 3]>
mesh.insert_attribute(Mesh::ATTRIBUTE_JOINT_INDEX, joint_indices); // Vec<[u16; 4]>
mesh.insert_attribute(Mesh::ATTRIBUTE_JOINT_WEIGHT, weights); // Vec<[f32; 4]>
let bounds = SkinnedMeshBounds::from_mesh(&mesh)?; Defensive patterns
Strategy: validation
Validate before calling
fn is_skinned_mesh_ready(mesh: &Mesh) -> bool {
mesh.attribute(Mesh::ATTRIBUTE_POSITION).is_some()
&& mesh.attribute(Mesh::ATTRIBUTE_JOINT_INDEX).is_some()
&& mesh.attribute(Mesh::ATTRIBUTE_JOINT_WEIGHT).is_some()
}
if is_skinned_mesh_ready(&mesh) {
let bounds = SkinnedMeshBounds::from_mesh(&mesh)?;
} Type guard
fn has_skin_attributes(mesh: &Mesh) -> bool {
matches!(mesh.attribute(Mesh::ATTRIBUTE_JOINT_INDEX), Some(VertexAttributeValues::Uint16x4(_)))
&& matches!(mesh.attribute(Mesh::ATTRIBUTE_JOINT_WEIGHT), Some(VertexAttributeValues::Float32x4(_)))
} Try / catch
match SkinnedMeshBounds::from_mesh(&mesh) {
Ok(bounds) => { /* use */ }
Err(SkinnedMeshBoundsError::MeshAttributeError(
MeshAttributeError::MissingAttribute(name),
)) => {
warn!("skipping bounds for mesh without attribute {name}");
}
Err(other) => warn!("skinning bounds failed: {other:?}"),
} Prevention
- Only invoke SkinnedMeshBounds::from_mesh on meshes known to carry skin attributes
- Insert JOINT_INDEX as Uint16x4 and JOINT_WEIGHT as Float32x4 whenever you author skinned meshes
- Gate systems with a query filter on SkinnedMesh so static meshes never reach this code
When it happens
Trigger: Calling SkinnedMeshBounds::from_mesh on a mesh that has no JOINT_INDEX or JOINT_WEIGHT attribute (e.g. a static mesh), or whose POSITION attribute was never inserted; also any direct use of InfluenceIterator::new on such a mesh.
Common situations: Running skinning/bounds systems on meshes imported without skin data; custom meshes built from scratch where skin attributes were forgotten; blending code that copies positions but drops joint attributes; assuming all meshes in a scene are skinned.
Related errors
- Attribute "{0}" has unexpected format {1:?}
- Indices weren't in chunks according to topology
- Failed to insert attribute. Invalid attribute format for {}.
- The mesh does not contain any joints that are skinned to ver
- Mesh is missing requested attribute: {name} ({id:?}, pipelin
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/7c4bc2963638efae.
Report an issue: GitHub.