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 point

View on GitHub (pinned to 396ca72708)

Solutions

  1. Only mutate the fragment for passes that output color: guard with if let Some(fragment) = &mut descriptor.fragment.
  2. Populate fragment: Some(FragmentState { .. }) when constructing descriptors that will be specialized.
  3. 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

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


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