bevyengine/bevy · error · ShaderCacheError
Pipeline could not be compiled because the following shader
Error message
Pipeline could not be compiled because the following shader could not be loaded: {0:?} What it means
Variant of ShaderCacheError from the shader/pipeline cache. A pipeline could not be compiled because one of the shaders it references is not loaded — the AssetId given to the cache has no loaded Shader behind it. This usually means the pipeline was queued before the shader asset finished (or failed) loading.
Source
Thrown at crates/bevy_shader/src/shader_cache.rs:538
}
}
_ => module_path.clone(),
}
}
fn display_name(&self, module_path: &wesl::syntax::ModulePath) -> Option<String> {
let module_path = self.canonical_path(module_path);
let asset_id = self.module_path_to_asset_id.get(&module_path)?;
let shader = self.shaders.get(asset_id)?;
Some(shader.path.clone())
}
}
/// Type of error returned by a `PipelineCache` when the creation of a GPU pipeline object failed.
#[expect(missing_docs, reason = "Enum variants are self-explanatory")]
#[derive(Error, Debug)]
pub enum ShaderCacheError {
#[error(
"Pipeline could not be compiled because the following shader could not be loaded: {0:?}"
)]
ShaderNotLoaded(AssetId<Shader>),
#[error("Failed to process shader:\n{0}")]
ProcessShaderError(String),
#[error("Shader import not yet available.")]
ShaderImportNotYetAvailable,
#[error("Could not create shader module: {0}")]
CreateShaderModule(String),
}
#[cfg(test)]
mod tests {
use super::*;
fn test_cache() -> ShaderCache<String, ()> {
ShaderCache::new((), |_, source, _| match source {
ShaderCacheSource::Wgsl(wgsl) => Ok(wgsl),View on GitHub (pinned to 227d3a6c66)
Solutions
- Hold strong handles to all shaders the pipeline needs until the pipeline is created
- Wait for LoadState::Loaded on the shader handle (e.g. recursively_dependencies_loaded) before queueing the pipeline
- Check the failed-loads channel to confirm the shader path actually resolves on disk
Example fix
// before
let shader = server.load_untyped("shader.wesl");
queue_pipeline(shader.id()); // ShaderNotLoaded
// after
let shader: Handle<Shader> = server.load("shader.wesl");
if server.load_state(&shader) == LoadState::Loaded {
queue_pipeline(shader);
} Defensive patterns
Strategy: validation
Validate before calling
if server.load_state(&shader_handle) != bevy::asset::LoadState::Loaded {
// defer pipeline creation until the shader is loaded
return;
} Try / catch
match pipeline_result {
Err(ShaderCacheError::ShaderNotLoaded(id)) => {
// re-queue the pipeline once the asset id reports Loaded
}
_ => {}
} Prevention
- Store strong Handles to every shader a pipeline references until the pipeline compiles
- Initialize custom render pipelines in systems that run after load state checks, not in plugin build()
When it happens
Trigger: Creating/queueing a pipeline whose ShaderPatches or shader AssetIds were derived from weak/unloaded handles, or after the shader asset failed to load; the cache looks up the shader by id, finds nothing, and returns ShaderNotLoaded(id).
Common situations: Custom render pipelines initialized during plugin build before the asset server loads shaders; hot-reload evicting a shader; typos in shader asset paths so the load never completes.
Related errors
- RenderPipelineDescriptor has no FragmentState configured
- Cannot resolve scene because the asset dependency {0} is not
- Failed to process shader: {0}
- Shader import not yet available.
- Field name should exist
AI-assisted analysis of bevyengine/bevy@227d3a6c66 (2026-08-20).
Data as JSON: /api/errors/253dd4461d3936c9.
Report an issue: GitHub.