bevyengine/bevy · error · MissingVertexAttributeError
Mesh is missing requested attribute: {name} ({id:?}, pipelin
Error message
Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?}) What it means
MissingVertexAttributeError is returned by MeshVertexBufferLayout::get_layout (crates/bevy_mesh/src/vertex.rs:146) while assembling the GPU VertexBufferLayout for a pipeline. A pipeline declares the vertex attributes its shader reads (as VertexAttributeDescriptors); if any requested attribute id is not present in the mesh's attribute set, layout building fails with this error, naming the attribute, its id, and the pipeline type when known. It is the standard signal that a shader's vertex input contract and the mesh's data disagree.
Source
Thrown at crates/bevy_mesh/src/vertex.rs:163
} else {
return Err(MissingVertexAttributeError {
id: attribute_descriptor.id,
name: attribute_descriptor.name,
pipeline_type: None,
});
}
}
Ok(VertexBufferLayout {
array_stride: self.layout.array_stride,
step_mode: self.layout.step_mode,
attributes,
})
}
}
#[derive(Error, Debug)]
#[error("Mesh is missing requested attribute: {name} ({id:?}, pipeline type: {pipeline_type:?})")]
pub struct MissingVertexAttributeError {
pub pipeline_type: Option<&'static str>,
id: MeshVertexAttributeId,
name: &'static str,
}
pub struct VertexAttributeDescriptor {
pub shader_location: u32,
pub id: MeshVertexAttributeId,
name: &'static str,
}
impl VertexAttributeDescriptor {
pub const fn new(shader_location: u32, id: MeshVertexAttributeId, name: &'static str) -> Self {
Self {
shader_location,
id,
name,View on GitHub (pinned to 396ca72708)
Solutions
- Add the missing attribute to the mesh: generate it with mesh.compute_normals() / compute_tangents(), or insert Mesh::ATTRIBUTE_UV_0 with matching vertex count
- If the shader does not truly need the attribute, remove it from the pipeline's layout descriptors so get_layout stops requesting it
- Select a different shader/pipeline variant for attribute-poor meshes (branch on mesh_vertex_buffer_layout.contains(...))
- Read the error's name/id to identify exactly which attribute the pipeline demanded
Example fix
// before: shader pipeline requires UVs the mesh does not have
let layout = mesh.get_vertex_buffer_layout(&[
Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
Mesh::ATTRIBUTE_UV_0.at_shader_location(1),
])?; // Err(MissingVertexAttributeError { name: "UV_0" .. })
// after: supply UVs (or drop location 1 from the layout)
let uvs: Vec<[f32; 2]> = (0..vertex_count).map(|_| [0.0, 0.0]).collect();
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, uvs); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the mesh provides every attribute the pipeline will request
let layout = mesh.get_mesh_vertex_buffer_layout(); // the mesh's attribute set
let required = [Mesh::ATTRIBUTE_POSITION, Mesh::ATTRIBUTE_NORMAL, Mesh::ATTRIBUTE_UV_0];
let missing: Vec<_> = required.iter().filter(|a| !layout.contains(**a)).collect();
if missing.is_empty() {
let vbl = layout.get_layout(&[
Mesh::ATTRIBUTE_POSITION.at_shader_location(0),
Mesh::ATTRIBUTE_NORMAL.at_shader_location(1),
Mesh::ATTRIBUTE_UV_0.at_shader_location(2),
])?;
} Type guard
fn mesh_has_attribute(mesh: &Mesh, attribute: MeshVertexAttribute) -> bool {
mesh.attribute(attribute).is_some()
} Try / catch
match mesh_layout.get_layout(&descriptors) {
Ok(vbl) => { /* create pipeline */ }
Err(e @ MissingVertexAttributeError { name, .. }) => {
error!("pipeline needs attribute {name} that the mesh lacks: {e}");
// fall back to a position-only pipeline variant or generate the attribute
}
} Prevention
- List the shader's vertex inputs in one place and assert the mesh satisfies them during pipeline specialization
- Generate derived attributes at load time: compute_normals(), compute_tangents(), or placeholder UVs
- Branch on mesh_vertex_buffer_layout.contains(...) to pick a pipeline variant that matches the mesh's data
When it happens
Trigger: Specializing or building a render pipeline whose layout requests attributes such as ATTRIBUTE_NORMAL, ATTRIBUTE_UV_0, ATTRIBUTE_TANGENT or ATTRIBUTE_JOINT_INDEX via mesh.get_vertex_buffer_layout()/MeshVertexBufferLayout::get_layout, while the mesh never inserted one of them.
Common situations: A custom Material/shader that samples UVs applied to a mesh generated without UVs; a pipeline that requires NORMALs on a raw TriangleList mesh built from just positions; skinned-shader pipelines run against static meshes; mixing procedurally-built meshes with assets authored in another tool.
Related errors
- Failed to insert attribute. Invalid attribute format for {}.
- Missing attribute "{0}"
- Attribute "{0}" has unexpected format {1:?}
- Mismatched vertex attribute values
- unsupported primitive mode
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/86c1b6533a30317b.
Report an issue: GitHub.