bevyengine/bevy · error

no safety checks are performed for spirv shaders. use `creat

Error message

no safety checks are performed for spirv shaders. use `create_shader_module` instead

What it means

RenderDevice::create_and_validate_shader_module is the validating wrapper around wgpu shader-module creation. When the 'spirv_shader_passthrough' feature is enabled and the descriptor's source is ShaderSource::SpirV, it deliberately panics: the validation path cannot check SPIR-V, so callers must use the passthrough method create_shader_module instead (which trusts the SPIR-V — hence the feature's name and the message's warning that no safety checks are performed).

Source

Thrown at crates/bevy_render/src/renderer/render_device.rs:106

        #[cfg(not(feature = "spirv_shader_passthrough"))]
        // SAFETY: the caller is responsible for upholding the safety requirements
        unsafe {
            self.device
                .create_shader_module_trusted(desc, wgpu::ShaderRuntimeChecks::unchecked())
        }
    }

    /// Creates and validates a [`ShaderModule`](wgpu::ShaderModule) from either SPIR-V or WGSL source code.
    ///
    /// See [`ValidateShader`](bevy_shader::ValidateShader) for more information on the tradeoffs involved with shader validation.
    #[inline]
    pub fn create_and_validate_shader_module(
        &self,
        desc: wgpu::ShaderModuleDescriptor,
    ) -> wgpu::ShaderModule {
        #[cfg(feature = "spirv_shader_passthrough")]
        match &desc.source {
            wgpu::ShaderSource::SpirV(_source) => panic!("no safety checks are performed for spirv shaders. use `create_shader_module` instead"),
            _ => self.device.create_shader_module(desc),
        }
        #[cfg(not(feature = "spirv_shader_passthrough"))]
        self.device.create_shader_module(desc)
    }

    /// Check for resource cleanups and mapping callbacks.
    ///
    /// Return `true` if the queue is empty, or `false` if there are more queue
    /// submissions still in flight. (Note that, unless access to the [`wgpu::Queue`] is
    /// coordinated somehow, this information could be out of date by the time
    /// the caller receives it. `Queue`s can be shared between threads, so
    /// other threads could submit new work at any time.)
    ///
    /// no-op on the web, device is automatically polled.
    #[inline]
    pub fn poll(&self, maintain: wgpu::PollType) -> Result<PollStatus, PollError> {
        self.device.poll(maintain)

View on GitHub (pinned to 396ca72708)

Solutions

  1. Call render_device.create_shader_module(desc) for SPIR-V sources (the passthrough path you opted into with the feature)
  2. Branch on the source: validate WGSL, pass through SPIR-V
  3. Convert the shader to WGSL and keep using the validating API everywhere

Example fix

// before
let module = render_device.create_and_validate_shader_module(desc); // panics on SpirV

// after
let module = match desc.source {
    wgpu::ShaderSource::SpirV(_) => render_device.create_shader_module(desc),
    _ => render_device.create_and_validate_shader_module(desc),
};
Defensive patterns

Strategy: validation

Validate before calling

// Route by source type before creating the module:
fn create_module(
    device: &RenderDevice,
    desc: wgpu::ShaderModuleDescriptor,
) -> wgpu::ShaderModule {
    match &desc.source {
        wgpu::ShaderSource::SpirV(_) => device.create_shader_module(desc),
        _ => device.create_and_validate_shader_module(desc),
    }
}

Type guard

fn is_spirv(desc: &wgpu::ShaderModuleDescriptor) -> bool {
    matches!(desc.source, wgpu::ShaderSource::SpirV(_))
}

Prevention

When it happens

Trigger: Calling render_device.create_and_validate_shader_module(wgpu::ShaderModuleDescriptor { source: ShaderSource::SpirV(bytes), .. }) while the spirv_shader_passthrough cargo feature is enabled in the project.

Common situations: Integrating precompiled SPIR-V pipelines with the passthrough feature turned on but routing the descriptor through the safe/validating helper; refactoring call sites from create_shader_module to the validating variant without branching on the source type.

Related errors


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