bevyengine/bevy · error · AssetExtractionError

The asset type does not support extraction. To clone the ass

Error message

The asset type does not support extraction. To clone the asset to the renderworld, use `RenderAssetUsages::default()`

What it means

Returned by RenderAsset::take_gpu_data (render_asset.rs:104) when a RenderAsset implementation keeps the default method body. 'take_gpu_data' is the extraction hook used when an asset is NOT simply cloned to the render world; if you opt out of cloning (e.g. RenderAssetUsages::MAIN_WORLD only) but never implement extraction, the extraction system gets this error. The message tells you the fix: use RenderAssetUsages::default() (MAIN_WORLD | RENDER_WORLD) so the asset is cloned instead of extracted.

Source

Thrown at crates/bevy_render/src/render_asset.rs:36

#[derive(Debug, Error)]
pub enum PrepareAssetError<E: Send + Sync + 'static> {
    #[error("Failed to prepare asset")]
    RetryNextUpdate(E),
    #[error("Failed to build bind group: {0}")]
    AsBindGroupError(AsBindGroupError),
}

/// The system set during which we extract modified assets to the render world.
#[derive(SystemSet, Clone, PartialEq, Eq, Debug, Hash)]
pub struct AssetExtractionSystems;

/// Error returned when an asset due for extraction has already been extracted
#[derive(Debug, Error)]
pub enum AssetExtractionError {
    #[error("The asset has already been extracted")]
    AlreadyExtracted,
    #[error("The asset type does not support extraction. To clone the asset to the renderworld, use `RenderAssetUsages::default()`")]
    NoExtractionImplementation,
}

/// Describes how an asset gets extracted and prepared for rendering.
///
/// In the [`ExtractSchedule`] step the [`RenderAsset::SourceAsset`] is transferred
/// from the "main world" into the "render world".
///
/// After that in the [`RenderSystems::PrepareAssets`] step the extracted asset
/// is transformed into its GPU-representation of type [`RenderAsset`].
pub trait RenderAsset: Send + Sync + 'static + Sized {
    /// The representation of the asset in the "main world".
    type SourceAsset: Asset + Clone;

    /// Specifies all ECS data required by [`RenderAsset::prepare_asset`].
    ///
    /// For convenience use the [`lifetimeless`](bevy_ecs::system::lifetimeless) [`SystemParam`].
    type Param: SystemParam;

View on GitHub (pinned to 396ca72708)

Solutions

  1. Return RenderAssetUsages::default() from asset_usage() so Bevy clones the asset into the render world instead of extracting it.
  2. Or override take_gpu_data to move the GPU-heavy data out of the source asset (e.g. core::mem::take) and return it as Ok(..).
  3. If you control the plugin setup and never want this asset on the GPU, do not register RenderAssetPlugin for that type so extraction never runs.

Example fix

// before
impl RenderAsset for GpuCustomMesh {
    type SourceAsset = CustomMesh;
    fn asset_usage(_s: &CustomMesh) -> RenderAssetUsages {
        RenderAssetUsages::MAIN_WORLD // extraction path, but take_gpu_data not implemented
    }
    // ...
}

// after (option A): clone instead of extract
fn asset_usage(_s: &CustomMesh) -> RenderAssetUsages {
    RenderAssetUsages::default()
}

// after (option B): keep MAIN_WORLD usage, implement extraction
fn take_gpu_data(
    source: &mut CustomMesh,
    _previous: Option<&Self>,
) -> Result<CustomMesh, AssetExtractionError> {
    Ok(core::mem::take(&mut source.gpu_data))
}
Defensive patterns

Strategy: validation

Validate before calling

// Before opting into the extraction path, confirm take_gpu_data is implemented
// for your RenderAsset; otherwise keep the clone-based default usages.
const EXTRACTION_IMPLEMENTED: bool = false;

fn asset_usage(source: &CustomAsset) -> RenderAssetUsages {
    if EXTRACTION_IMPLEMENTED {
        RenderAssetUsages::MAIN_WORLD
    } else {
        RenderAssetUsages::default() // clone to the render world
    }
}

Prevention

When it happens

Trigger: Implementing RenderAsset for a custom asset, overriding asset_usage() to return something other than RenderAssetUsages::default() (typically MAIN_WORLD-only to avoid duplicating data across worlds), and leaving take_gpu_data at its default which unconditionally returns Err(AssetExtractionError::NoExtractionImplementation).

Common situations: Custom mesh/texture-like assets where the author wants zero-copy transfer to the render world; Bevy version upgrades that introduced the take_gpu_data/AssetExtractionError API; code copied from examples that use RenderAssetUsages::MAIN_WORLD without the matching extraction impl.

Related errors


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