bevyengine/bevy · error · MeshAccessError

The requested mesh data wasn't found in this mesh

Error message

The requested mesh data wasn't found in this mesh

What it means

MeshAccessError::NotFound comes from the MeshExtractableData accessors when the requested slot holds NoData (crates/bevy_mesh/src/mesh.rs:64), or from attribute-id lookups that miss (mesh.rs:535, 613, 664). It means the requested vertex attribute or index data simply does not exist in this mesh: it was never inserted, or the attribute id is absent from the mesh's map.

Source

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

use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bytemuck::cast_slice;
use core::hash::{Hash, Hasher};
use core::ptr;
#[cfg(feature = "serialize")]
use serde::{Deserialize, Serialize};
use thiserror::Error;
use tracing::warn;
use wgpu_types::{VertexAttribute, VertexFormat, VertexStepMode, WriteOnly};

pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;

/// Error from accessing mesh vertex attributes or indices
#[derive(Error, Debug, Clone)]
pub enum MeshAccessError {
    #[error("The mesh vertex/index data has been extracted to the RenderWorld (via `Mesh::asset_usage`)")]
    ExtractedToRenderWorld,
    #[error("The requested mesh data wasn't found in this mesh")]
    NotFound,
}

const MESH_EXTRACTED_ERROR: &str = "Mesh has been extracted to RenderWorld. To access vertex attributes, the mesh `asset_usage` must include `MAIN_WORLD`";

// storage for extractable data with access methods which return errors if the
// contents have already been extracted
#[derive(Debug, Clone, PartialEq, Reflect, Default)]
enum MeshExtractableData<T> {
    Data(T),
    #[default]
    NoData,
    ExtractedToRenderWorld,
}

impl<T> MeshExtractableData<T> {
    // get a reference to internal data. returns error if data has been extracted, or if no
    // data exists

View on GitHub (pinned to 396ca72708)

Solutions

  1. Insert the attribute before accessing it (e.g. mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, ...))
  2. Check presence first with the Option-returning API: mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_some()
  3. Handle Err(MeshAccessError::NotFound) by supplying a sensible default or skipping the mesh

Example fix

// before
let normals = mesh.try_attribute_mut(Mesh::ATTRIBUTE_NORMAL)?; // Err(NotFound)

// after
if mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_none() {
    mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vec![[0.0, 1.0, 0.0]; mesh.count_vertices()]);
}
let normals = mesh.try_attribute_mut(Mesh::ATTRIBUTE_NORMAL)?;
Defensive patterns

Strategy: try-catch

Validate before calling

let has_normals = mesh.attribute(Mesh::ATTRIBUTE_NORMAL).is_some();
if !has_normals {
    mesh.insert_attribute(
        Mesh::ATTRIBUTE_NORMAL,
        vec![[0.0, 1.0, 0.0]; mesh.count_vertices()],
    );
}

Type guard

fn has_attribute(mesh: &Mesh, id: MeshVertexAttributeId) -> bool {
    mesh.attribute_id(id).is_some()
}

Try / catch

match mesh.try_attribute(Mesh::ATTRIBUTE_NORMAL) {
    Ok(values) => { /* use values */ }
    Err(MeshAccessError::NotFound) => { /* attribute absent: insert it or skip */ }
    Err(MeshAccessError::ExtractedToRenderWorld) => { /* fix asset_usage or use a CPU copy */ }
}

Prevention

When it happens

Trigger: Accessing a required attribute that was never inserted (e.g. normals on a primitive built without them) via the try_attribute/as_mut APIs; calling mutating accessors on a mesh that holds no attributes or indices at all (NoData state).

Common situations: Assuming every mesh has normals/tangents/Uvs; procedurally generated meshes that skip optional attributes; code that queries an attribute id by a different name/id than the one inserted.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/374b6c4120771838. Report an issue: GitHub.