gfx-rs/wgpu · error

found `ShaderSource::Dummy`

Error message

found `ShaderSource::Dummy`

What it means

The web backend's shader module creation matches on ShaderSource and panics if it encounters ShaderSource::Dummy. Dummy is an internal placeholder source (used for dummy/passthrough pipelines on native) that carries no real WGSL/SPIR-V, so there is nothing to send to the browser; hitting it means internal-only source reached the create_shader_module path.

Source

Thrown at wgpu/src/backend/webgpu.rs:2086

                    shader_module,
                    WebShaderCompilationInfo::Wgsl {
                        source: code.to_string(),
                    },
                ))
            }
            #[cfg(feature = "naga-ir")]
            crate::ShaderSource::Naga(ref module) => {
                validate_transformed_shader_module(module, "", &desc).map(|v| {
                    (
                        v,
                        WebShaderCompilationInfo::Transformed {
                            compilation_info: crate::CompilationInfo { messages: vec![] },
                        },
                    )
                })
            }
            crate::ShaderSource::Dummy(_) => {
                panic!("found `ShaderSource::Dummy`")
            }
        };

        #[cfg(naga)]
        fn validate_transformed_shader_module(
            module: &naga::Module,
            source: &str,
            desc: &crate::ShaderModuleDescriptor<'_>,
        ) -> Result<webgpu_sys::GpuShaderModuleDescriptor, crate::CompilationInfo> {
            use naga::{back, valid};
            let mut validator =
                valid::Validator::new(valid::ValidationFlags::all(), valid::Capabilities::all());
            let module_info = validator.validate(module).map_err(|err| {
                crate::CompilationInfo::from(naga::error::ShaderError {
                    source: source.to_string(),
                    label: desc.label.map(|s| s.to_string()),
                    inner: err,
                })

View on GitHub (pinned to 3e11ff59bf)

Solutions

  1. Always pass a real ShaderSource::Wgsl (or SpirV) to create_shader_module on web.
  2. Do not use create_shader_module_passthrough / Dummy on the web backend; reserve it for native-only paths.
  3. Guard code paths that fall back to Dummy so they are skipped when running under wasm32.

Example fix

// before
let module = device.create_shader_module(wgpu::ShaderModuleDescriptor { source: wgpu::ShaderSource::Dummy(Default::default()), .. });
// after
let module = device.create_shader_module(wgpu::ShaderModuleDescriptor { source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()), .. });
Defensive patterns

Strategy: validation

Validate before calling

if let wgpu::ShaderSource::Dummy(_) = descriptor.source {
    panic!("ShaderSource::Dummy is not valid for create_shader_module on web");
}

Type guard

fn has_real_source(d: &wgpu::ShaderModuleDescriptor) -> bool {
    !matches!(d.source, wgpu::ShaderSource::Dummy(_))
}

Prevention

When it happens

Trigger: Calling device.create_shader_module (or create_shader_module_passthrough) with ShaderSource::Dummy on the web backend; using internal APIs that inject a Dummy source for testing or pipeline layouts on web.

Common situations: Misuse of internal/wgpu-core style APIs from application code; passthrough pipeline helpers intended for native only; library code that substitutes Dummy source when real shader text is unavailable.

Related errors


AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03). Data as JSON: /api/errors/6d69e61201b0d77e. Report an issue: GitHub.