bevyengine/bevy · critical

Data ranges have no binding resource

Error message

Data ranges have no binding resource

What it means

UnpreparedBindingResource::get_binding() (bind_group.rs:871) panics on the Data variant because a raw value range corresponds to no binding by itself - it must be packed into a buffer by the MaterialBindGroupAllocator before it can be bound. The panic mirrors the OwnedBindingResource::Data case one level earlier, on the unprepared representation.

Source

Thrown at crates/bevy_render/src/render_resource/bind_group.rs:871

            UnpreparedBindingResource::Sampler(_, sampler) => BindingResource::Sampler(sampler),
            UnpreparedBindingResource::ShaderBuffer(shader_buffer) => {
                // Fetch the raw buffer from the
                // `shader_buffer_assets`. If it's not there,
                // use the fallback buffer.
                match shader_buffer_assets.get(shader_buffer.id()) {
                    Some(shader_buffer) => BindingResource::Buffer(BufferBinding {
                        buffer: &shader_buffer.buffer,
                        offset: 0,
                        size: None,
                    }),
                    None => BindingResource::Buffer(BufferBinding {
                        buffer: fallback_buffer,
                        offset: 0,
                        size: None,
                    }),
                }
            }
            UnpreparedBindingResource::Data(_) => panic!("Data ranges have no binding resource"),
        }
    }
}

/// Converts a value to a [`ShaderType`] for use in a bind group.
///
/// This is automatically implemented for references that implement [`Into`].
/// Generally normal [`Into`] / [`From`] impls should be preferred, but
/// sometimes additional runtime metadata is required.
/// This exists largely to make some [`AsBindGroup`] use cases easier.
pub trait AsBindGroupShaderType<T: ShaderType> {
    /// Return the `T` [`ShaderType`] for `self`. When used in [`AsBindGroup`]
    /// derives, it is safe to assume that all images in `self` exist.
    fn as_bind_group_shader_type(&self, images: &RenderAssets<GpuImage>) -> T;
}

impl<T, U: ShaderType> AsBindGroupShaderType<U> for T
where

View on GitHub (pinned to 396ca72708)

Solutions

  1. Route Data through the MaterialBindGroupAllocator (packing into a slotted buffer) rather than get_binding().
  2. Use Buffer/TextureView/Sampler variants for resources you intend to bind directly.
  3. Go through as_bind_group()/the standard material preparation, which handles Data packing.

Example fix

// before
let binding = unprepared.get_binding(); // panics on Data(_)

// after
match &unprepared {
    UnpreparedBindingResource::Data(_) => { /* handled by MaterialBindGroupAllocator packing */ }
    other => { let binding = other.get_binding(); }
}
Defensive patterns

Strategy: type-guard

Type guard

fn unprepared_is_directly_bindable(res: &UnpreparedBindingResource) -> bool {
    !matches!(res, UnpreparedBindingResource::Data(_))
}

Prevention

When it happens

Trigger: Calling get_binding() on UnpreparedBindingResource::Data - typical when hand-building a bind group from an unprepared material's binding list instead of using the allocator/packing path.

Common situations: Custom material code that iterates unprepared bindings uniformly; data-slot-based materials (values packed into shared buffers); migrating older code that assumed every binding had a direct resource.

Related errors


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