bevyengine/bevy · error · MeshAccessError

The mesh vertex/index data has been extracted to the RenderW

Error message

The mesh vertex/index data has been extracted to the RenderWorld (via `Mesh::asset_usage`)

What it means

When a Mesh asset is used for rendering and its asset_usage omits MAIN_WORLD, Bevy extracts (moves) the vertex/index data to the RenderWorld and drops the CPU copy. Any later CPU-side access through the MeshExtractableData accessors returns MeshAccessError::ExtractedToRenderWorld. The companion hint constant MESH_EXTRACTED_ERROR explains that asset_usage must include MAIN_WORLD for CPU access.

Source

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

};
use bevy_platform::collections::{hash_map, HashMap};
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> {

View on GitHub (pinned to 396ca72708)

Solutions

  1. Keep MAIN_WORLD in asset_usage: mesh.asset_usage = RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD
  2. Finish all CPU-side reads/edits before the mesh is added to Assets<Mesh> and rendered
  3. Store a separate CPU-side copy (e.g. raw Vecs or a clone before extraction) for systems that need the data later

Example fix

// before
let mut mesh = Mesh::from(shape::Cube::default());
mesh.asset_usage = RenderAssetUsages::RENDER_WORLD;
// ... later, after render extraction:
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals); // Err(ExtractedToRenderWorld)

// after
let mut mesh = Mesh::from(shape::Cube::default());
mesh.asset_usage = RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD;
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, normals); // Ok
Defensive patterns

Strategy: validation

Validate before calling

fn mesh_usable_on_cpu(mesh: &Mesh) -> bool {
    mesh.asset_usage.contains(RenderAssetUsages::MAIN_WORLD)
}

if mesh_usable_on_cpu(&mesh) {
    let values = mesh.try_attributes()?;
}

Try / catch

match mesh.try_attributes() {
    Ok(attributes) => { /* read attributes */ }
    Err(MeshAccessError::ExtractedToRenderWorld) => {
        // data lives only in the RenderWorld: fix asset_usage or use a CPU copy
    }
    Err(MeshAccessError::NotFound) => { /* mesh has no attributes at all */ }
}

Prevention

When it happens

Trigger: Calling mesh.attributes(), mesh.indices_mut(), mesh.try_insert_attribute(), mesh.triangles_mut() or similar accessors after the mesh was rendered with asset_usage = RenderAssetUsages::RENDER_WORLD only.

Common situations: Optimizing memory by dropping MAIN_WORLD, then a runtime system (physics, picking, mesh editing, serialization) still needs CPU access; hot-reload code that mutates already-uploaded meshes.

Related errors


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