bevyengine/bevy · warning · PrepareAssetError

Failed to prepare asset

Error message

Failed to prepare asset

What it means

`PrepareAssetError::RetryNextUpdate(E)` is the soft-failure variant of the render-asset pipeline: an asset's `prepare_asset` step could not complete yet (for example a dependency image has not loaded, or `AsBindGroupError::RetryNextUpdate` was returned). The prepare system catches it and queues the asset for the next update instead of failing; it is also the variant your own `RenderAsset` impls should return for transient failures. Its Display text is the string shown.

Source

Thrown at crates/bevy_render/src/erased_render_asset.rs:22

};
use bevy_app::{App, Plugin, SubApp};
use bevy_asset::RenderAssetUsages;
use bevy_asset::{Asset, AssetEvent, AssetId, Assets, UntypedAssetId};
use bevy_ecs::{
    prelude::{Commands, IntoScheduleConfigs, Local, MessageReader, ResMut, Resource},
    schedule::{ScheduleConfigs, SystemSet},
    system::{ScheduleSystem, StaticSystemParam, SystemParam, SystemParamItem, SystemState},
    world::{FromWorld, Mut},
};
use bevy_log::{debug, error};
use bevy_platform::collections::{HashMap, HashSet};
use bevy_render::render_asset::RenderAssetBytesPerFrameLimiter;
use core::marker::PhantomData;
use thiserror::Error;

#[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;

/// Describes how an asset gets extracted and prepared for rendering.
///
/// In the [`ExtractSchedule`] step the [`ErasedRenderAsset::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 [`ErasedRenderAsset`].
pub trait ErasedRenderAsset: Send + Sync + 'static {
    /// The representation of the asset in the "main world".

View on GitHub (pinned to 396ca72708)

Solutions

  1. If you emit it from your own impl: ensure the underlying condition eventually clears, otherwise the asset retries every frame forever
  2. Pre-load dependencies (images, buffers) before spawning the asset that prepares against them
  3. For genuinely permanent failures, log or return a hard error instead of retrying indefinitely

Example fix

// before
fn prepare(asset: Self::SourceAsset, ...) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
    let Some(dep) = images.get(&asset.dep) else { panic!("dep not loaded") };
    // ...
}

// after
fn prepare(asset: Self::SourceAsset, ...) -> Result<Self::PreparedAsset, PrepareAssetError<Self>> {
    let Some(dep) = images.get(&asset.dep) else {
        return Err(PrepareAssetError::RetryNextUpdate(asset));
    };
    // ...
}
Defensive patterns

Strategy: retry

Try / catch

// in your RenderAsset::prepare_asset implementations
match result {
    Err(PrepareAssetError::RetryNextUpdate(asset)) => {
        return Err(PrepareAssetError::RetryNextUpdate(asset)); // engine retries next frame
    }
    Err(PrepareAssetError::AsBindGroupError(e)) => {
        error!("bind group failed: {e}");
    }
    Ok(prepared) => { /* insert */ }
}

Prevention

When it happens

Trigger: A material or render asset being prepared while a dependency is not yet resident (texture still uploading, bind group inputs missing), causing `prepare_asset` to return `Err(PrepareAssetError::RetryNextUpdate(..))`; the engine retries next frame without logging.

Common situations: Startup frames before textures finish loading; custom RenderAsset impls that depend on other GPU resources; mistaking this for a hard error because the Display text says "Failed to prepare asset" while the engine simply retries.

Related errors


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