bevyengine/bevy · error · NoFragmentStateError
RenderPipelineDescriptor has no FragmentState configured
Error message
RenderPipelineDescriptor has no FragmentState configured
What it means
RenderPipelineDescriptor::fragment_mut() returns NoFragmentStateError when the descriptor's fragment field is None (crates/bevy_material/src/descriptor.rs:58). Descriptors legitimately lack a fragment state for depth-only-style pipelines, but any code that tries to mutate the fragment stage will get this error — Bevy's own gizmo, fullscreen-material, CAS and TAA specializers all call fragment_mut() with ? propagation.
Source
Thrown at crates/bevy_material/src/descriptor.rs:54
/// Supply 0 if the pipeline doesn't use push constants/immediates.
pub immediate_size: u32,
/// The compiled vertex stage, its entry point, and the input buffers layout.
pub vertex: VertexState,
/// The properties of the pipeline at the primitive assembly and rasterization level.
pub primitive: PrimitiveState,
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
pub depth_stencil: Option<DepthStencilState>,
/// The multi-sampling properties of the pipeline.
pub multisample: MultisampleState,
/// The compiled fragment stage, its entry point, and the color targets.
pub fragment: Option<FragmentState>,
/// Whether to zero-initialize workgroup memory by default. If you're not sure, set this to true.
/// If this is false, reading from workgroup variables before writing to them will result in garbage values.
pub zero_initialize_workgroup_memory: bool,
}
#[derive(Copy, Clone, Debug, Error)]
#[error("RenderPipelineDescriptor has no FragmentState configured")]
pub struct NoFragmentStateError;
impl RenderPipelineDescriptor {
pub fn fragment_mut(&mut self) -> Result<&mut FragmentState, NoFragmentStateError> {
self.fragment.as_mut().ok_or(NoFragmentStateError)
}
pub fn set_layout(&mut self, index: usize, layout: BindGroupLayoutDescriptor) {
filling_set_at(&mut self.layout, index, bevy_utils::default(), layout);
}
}
#[derive(Clone, Debug, PartialEq, Default)]
pub struct VertexState {
/// The compiled shader module for this stage.
pub shader: Handle<Shader>,
pub shader_defs: Vec<ShaderDefVal>,
/// The name of the entry point in the compiled shader, or `None` if the default entry pointView on GitHub (pinned to 396ca72708)
Solutions
- Only mutate the fragment for passes that output color: guard with if let Some(fragment) = &mut descriptor.fragment.
- Populate fragment: Some(FragmentState { .. }) when constructing descriptors that will be specialized.
- Propagate the Result with ? from your specialization function so the failure surfaces as a pipeline error.
Example fix
// before
let fragment = descriptor.fragment_mut()?; // Err when fragment is None (depth-only)
fragment.shader_defs.push("MY_DEF".into());
// after
if let Some(fragment) = &mut descriptor.fragment {
fragment.shader_defs.push("MY_DEF".into());
} Defensive patterns
Strategy: validation
Validate before calling
fn configure_fragment(descriptor: &mut RenderPipelineDescriptor) {
if descriptor.fragment.is_some() {
let fragment = descriptor.fragment_mut().expect("checked above");
fragment.shader_defs.push("MY_DEF".into());
}
} Try / catch
match descriptor.fragment_mut() {
Ok(fragment) => fragment.shader_defs.push("MY_DEF".into()),
Err(NoFragmentStateError) => { /* depth-only pipeline: nothing to specialize */ }
} Prevention
- Never assume a descriptor has a fragment; depth-only pipelines are common.
- Set fragment: Some(..) at construction for pipelines you will specialize for color output.
- Propagate ? in specializers so the error surfaces with pipeline context.
When it happens
Trigger: Calling fragment_mut() (directly or via ? in a pipeline specialization) on a descriptor built with fragment: None — typically a prepass/depth-derived or otherwise color-less descriptor being specialized as if it rendered color.
Common situations: Custom Material specializations that assume every pipeline has a fragment; base descriptors cloned from depth-only passes; writing a new post-process material and copying a depth-only template.
Related errors
- Failed to build bind group: {0}
- Pipeline could not be compiled because the following shader
- Failed to process shader: {0}
- Shader import not yet available.
- Could not create shader module: {0}
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/ed37eccb0c8135fe.
Report an issue: GitHub.