bevyengine/bevy · error · AsBindGroupError
InvalidSamplerType
InvalidSamplerType
Error message
At binding index {0}, the provided image sampler `{1}` does not match the required sampler type(s) `{2}`. What it means
AsBindGroupError::InvalidSamplerType(index, provided, required) is reported by as_bind_group when the sampler attached to an image does not match the sampler type(s) the bind group layout requires at that binding index: filtering vs non-filtering vs comparison. The payload names the offending binding index, the sampler actually provided, and the type(s) the shader/layout declared, so you can locate the mismatch precisely.
Source
Thrown at crates/bevy_render/src/render_resource/bind_group.rs:646
force_no_bindless: bool,
) -> Vec<BindGroupLayoutEntry>
where
Self: Sized;
fn bindless_descriptor() -> Option<BindlessDescriptor> {
None
}
}
/// An error that occurs during [`AsBindGroup::as_bind_group`] calls.
#[derive(Debug, Error)]
pub enum AsBindGroupError {
/// The bind group could not be generated. Try again next frame.
#[error("The bind group could not be generated")]
RetryNextUpdate,
#[error("Create the bind group via `as_bind_group()` instead")]
CreateBindGroupDirectly,
#[error("At binding index {0}, the provided image sampler `{1}` does not match the required sampler type(s) `{2}`.")]
InvalidSamplerType(u32, String, String),
}
/// A prepared bind group returned as a result of [`AsBindGroup::as_bind_group`].
pub struct PreparedBindGroup {
pub bindings: BindingResources,
pub bind_group: BindGroup,
}
impl PreparedBindGroup {
pub(crate) fn unprepare(&self) -> BindGroupBuilder {
let mut data_buffer = vec![];
BindGroupBuilder {
binding_resources: UnpreparedBindingResources(
self.bindings
.iter()
.map(|(binding, owned_binding_resource)| {
let unprepared_binding_resource = match owned_binding_resource {View on GitHub (pinned to 396ca72708)
Solutions
- Make the image's sampler match the shader: for sampler_comparison set image.sampler = TextureSampler::Descriptor(SamplerDescriptor { compare: Some(CompareFunction::LessEqual), ..default() }).
- For non-filterable formats, use TextureSampler::NonFiltering and keep the shader declaration consistent.
- Use the binding index from the message to find the exact field/attribute to fix; check the derive attributes' sampler types.
Example fix
// before: shader declares a comparison sampler but the image keeps the default filtering one
// @group(2) @binding(0) var shadow_sampler: sampler_comparison;
let image = assets.get(&shadow_texture_handle).unwrap(); // sampler == TextureSampler::Default
// after
let mut image = Image::new(...);
image.sampler = TextureSampler::Descriptor(bevy_render::render_resource::SamplerDescriptor {
compare: Some(bevy_render::render_resource::CompareFunction::LessEqual),
..Default::default()
}); Defensive patterns
Strategy: validation
Validate before calling
// Keep image sampler and shader declaration in sync before building materials:
fn sampler_for_shader(needs_comparison: bool) -> TextureSampler {
if needs_comparison {
TextureSampler::Descriptor(SamplerDescriptor {
compare: Some(CompareFunction::LessEqual),
..Default::default()
})
} else {
TextureSampler::Default
}
} Try / catch
match material.as_bind_group(&layout, device, queue, &mut param) {
Err(AsBindGroupError::InvalidSamplerType(index, provided, required)) => {
error!("binding {index}: sampler {provided} does not satisfy {required}");
// fix image.sampler or the shader declaration, then retry
}
other => other?,
} Prevention
- Whenever a shader declares sampler_comparison, set the image's sampler to a comparison descriptor in the same change.
- Use TextureSampler::NonFiltering for non-filterable (integer/depth) formats and keep declarations consistent.
- Use the error's binding index to jump straight to the offending field instead of guessing.
When it happens
Trigger: Declaring a comparison sampler (sampler_comparison) in WGSL while the image keeps the default filtering TextureSampler; using a non-filterable texture format with a filtering sampler declaration; or specifying the wrong sampler type in #[derive(AsBindGroup)] binding attributes.
Common situations: Shadow-mapping materials that forget to switch the sampled image to a comparison sampler descriptor; integer or depth formats (non-filterable) sampled as if filterable; shader code copied between filtering and non-filtering contexts; upgrading engines where sampler defaults changed.
Related errors
- Could not load texture file: {0}
- Error reading image file {path}: {error}.
- Failed to prepare atmosphere bind groups. Light uniform buff
- Failed to build bind group: {0}
- RetryNextUpdate
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/59c8e6fa84b9e29e.
Report an issue: GitHub.