bevyengine/bevy · error · ShaderCacheError
Failed to process shader: {0}
Error message
Failed to process shader:
{0} What it means
ShaderCacheError::ProcessShaderError is returned by ShaderCache::get when the Wesl compiler (wesl::compile_sourcemap) fails to process a shader whose source is Source::Wesl. The wrapped string is the raw Wesl compiler error. It is also returned directly when a Wesl shader's import_path cannot be parsed into a module path ("Wesl shader `...` has a malformed import path"). PipelineCache logs the error and marks the pipeline as errored; the app keeps running but that pipeline never renders.
Source
Thrown at crates/bevy_shader/src/shader_cache.rs:542
}
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),
_ => panic!("expected wgsl output"),
})
}
View on GitHub (pinned to 227d3a6c66)
Solutions
- Read the embedded compiler message first — it names the file, line, and construct the Wesl compiler rejected
- Fix the reported syntax error or malformed import path in the .wesl source
- Remove `const` declarations that duplicate integer/uint shader defs; they are injected automatically from ShaderDefVal::Int/UInt
- Verify every import path matches the actual asset path of the imported shader
- If hot-reload state looks stale, restart the app to force a full shader recompile
Example fix
// before — ProcessShaderError: name 'PIXEL_RATIO' is already defined
// (the integer shader def already injects `const PIXEL_RATIO = 2;`)
const PIXEL_RATIO = 2u;
fn fs(in: VertexOutput) -> vec4<f32> {
let s = in.pos.x * f32(PIXEL_RATIO);
return vec4<f32>(s, 0.0, 0.0, 1.0);
}
// after — rely on the injected constant, do not redeclare it
fn fs(in: VertexOutput) -> vec4<f32> {
let s = in.pos.x * f32(PIXEL_RATIO);
return vec4<f32>(s, 0.0, 0.0, 1.0);
} Defensive patterns
Strategy: try-catch
Try / catch
match shader_cache.get(pipeline_id, shader_id, &shader_defs) {
Ok(module) => { /* use module */ }
Err(ShaderCacheError::ProcessShaderError(msg)) => {
error!("shader compile failed, skipping pipeline: {msg}");
// fall back to a known-good pipeline or mark the object unrenderable
}
Err(e) => return Err(e),
} Prevention
- Lint shader assets in CI by compiling .wesl sources with the wesl compiler so mistakes fail the build, not the run
- Never declare `const` names that are also passed as ShaderDefVal::Int/UInt defs — the cache injects them automatically
- Keep import paths in shaders identical to the imported asset paths
When it happens
Trigger: Calling ShaderCache::get (directly or via PipelineCache pipeline creation) on a Wesl shader that fails wesl::compile_sourcemap with a non-module-not-found error: WGSL/Wesl syntax errors, duplicate declarations, or a const in the shader colliding with an integer shader def (the cache auto-injects `const name = value;` for every ShaderDefVal::Int/UInt def, see shader_cache.rs:277-280), or a Wesl asset whose import_path wesl_module_path() cannot parse.
Common situations: Typos introduced while hot-reloading .wesl shader files; declaring constants in shader code that are also passed as integer shader_defs; migrating shaders from naga-oil `#import` preprocessing to Wesl import syntax across Bevy upgrades; passing shader defs whose names clash with Wesl reserved words.
Related errors
- Shader import not yet available.
- RenderPipelineDescriptor has no FragmentState configured
- spirv not yet implemented
- Pipeline could not be compiled because the following shader
- Could not create shader module: {0}
AI-assisted analysis of bevyengine/bevy@227d3a6c66 (2026-08-20).
Data as JSON: /api/errors/f1217ecac93e022e.
Report an issue: GitHub.