bevyengine/bevy · error · MeshAttributeCompressionError

Vertex attribute {0:?} doesn't exist

Error message

Vertex attribute {0:?} doesn't exist

What it means

MeshAttributeCompressionError::MissingAttribute is thrown when a compression/quantization operation on a Mesh references a vertex attribute id that the mesh does not contain. The library looks up the attribute by MeshVertexAttributeId before compressing it and fails if no such attribute exists in the mesh's attribute table.

Source

Thrown at crates/bevy_mesh/src/mesh.rs:3177

                        warn!(
                            "Deserialized mesh contains custom vertex attribute {attribute:?} that \
                            was not specified with `MeshDeserializer::add_custom_vertex_attribute`. Ignoring."
                        );
                        return None;
                    };
                    Some((id, data))
                })
                .collect()),
            indices: serialized_mesh.indices.into(),
            ..Mesh::new(serialized_mesh.primitive_topology, RenderAssetUsages::default())
        }
    }
}

/// Error that can occur when compressing/quantizing mesh vertex attributes.
#[derive(Error, Debug, Clone)]
pub enum MeshAttributeCompressionError {
    #[error("Vertex attribute {0:?} doesn't exist")]
    MissingAttribute(MeshVertexAttributeId),
    #[error("Vertex attribute {0:?} must not be empty")]
    EmptyAttribute(MeshVertexAttribute),
    #[error(
        "Vertex attribute {attr:?} must have format {expected:?} before compressing/quantizing"
    )]
    UnsupportedAttributeForCompression {
        attr: MeshVertexAttribute,
        expected: VertexFormat,
    },
    #[error("Vertex attribute {attr:?} must have format `Float32`, `Float32x2` or `Float32x4` before quantizing")]
    UnsupportedAttributeForQuantizing { attr: MeshVertexAttribute },
}

/// Error that can occur when calling [`Mesh::merge_duplicate_vertices`]
#[derive(Error, Debug, Clone)]
pub enum MeshMergeDuplicateVerticesError {
    #[error("Index attribute already set.")]

View on GitHub (pinned to 8d743eb7dc)

Solutions

  1. Verify the attribute exists before compressing: check mesh.contains_attribute(id) (or try mesh.attribute(id))
  2. Confirm you are using the MeshVertexAttribute constant (whose id matches the one inserted via insert_attribute) and not a separately constructed MeshVertexAttributeId
  3. Ensure the mesh asset you operate on actually carries the attribute (e.g. positions/normals/uv) at that point in the pipeline
  4. Insert or restore the attribute before calling compression APIs

Example fix

// before
mesh.compress_attribute(Mesh::ATTRIBUTE_TANGENT.id);
// after
if mesh.contains_attribute(Mesh::ATTRIBUTE_TANGENT.id) {
    mesh.compress_attribute(Mesh::ATTRIBUTE_TANGENT.id);
}
Defensive patterns

Strategy: validation

Validate before calling

fn attribute_exists(mesh: &Mesh, id: MeshVertexAttributeId) -> bool {
    mesh.contains_attribute(id)
}
// call only if attribute_exists(&mesh, my_attr.id())

Type guard

fn has_attr(mesh: &Mesh, id: MeshVertexAttributeId) -> Option<&MeshVertexAttributeData> {
    mesh.attribute(id)
}

Try / catch

match mesh.compress_attribute(id) {
    Ok(_) => {},
    Err(MeshAttributeCompressionError::MissingAttribute(missing)) => {
        warn!("attribute {:?} not present; skipping compression", missing);
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling Mesh::compress_attribute or Mesh::quantize_attribute with a MeshVertexAttributeId whose attribute was never inserted into the mesh, or was removed, or whose id was constructed with a different format/id than the one stored.

Common situations: Typos in custom attribute ids, operating on a mesh loaded from an asset that lacks the attribute, calling compression after removing attributes, or mismatching a locally-defined MeshVertexAttribute constant with the id actually registered on the mesh.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of bevyengine/bevy@8d743eb7dc (2026-09-13). Data as JSON: /api/errors/8fff1fb4d660eabe. Report an issue: GitHub.