gfx-rs/wgpu · error

byte slice does not start with SPIR-V magic number. Make sur

Error message

byte slice does not start with SPIR-V magic number. Make sure you are using a binary SPIR-V file.

What it means

This panic is thrown by wgpu's `util::make_spirv_raw`/`make_spirv_const` helpers when the input byte slice does not begin with the SPIR-V magic number 0x07230203. These helpers only accept binary SPIR-V modules; the magic check is the first sanity gate before any other decoding. Passing WGSL text, GLSL source, or a corrupted/truncated binary will hit this panic.

Source

Thrown at wgpu/src/util/spirv.rs:70

            } else {
                None
            }
        }
        _ => None, // fallthrough case = between 1 and 3 bytes
    };

    match found_magic_number {
        Some(needs_byte_swap) => {
            // Note: this assertion is relied upon for the soundness of `make_spirv_const()`.
            assert!(
                bytes.len().is_multiple_of(mem::size_of::<u32>()),
                "SPIR-V data must be a multiple of 4 bytes long"
            );

            needs_byte_swap
        }
        None => {
            panic!(
                "byte slice does not start with SPIR-V magic number. \
            Make sure you are using a binary SPIR-V file."
            );
        }
    }
}

#[cfg_attr(not(feature = "spirv"), expect(rustdoc::broken_intra_doc_links))]
/// Version of [`make_spirv()`] intended for use with
/// [`Device::create_shader_module_passthrough()`].
///
/// Returns a raw slice instead of [`ShaderSource`].
///
/// # Panics
///
/// This function panics if:
///
/// - `data.len()` is not a multiple of 4

View on GitHub (pinned to 3e11ff59bf)

Solutions

  1. Compile your shader to binary SPIR-V (e.g. glslc shader.comp -o shader.spv or glslangValidator -V) and pass the .spv bytes
  2. If you are passing source code, switch to the correct ingestion API: create the shader module from WGSL via ShaderModuleDescriptor with source=Wgsl, or use naga to transpile
  3. Verify the first 4 bytes of your data are [0x03, 0x02, 0x23, 0x07] (or the reversed word) before calling the helper
  4. Check your build pipeline actually produced and embedded the compiled binary (print bytes.len() and the magic word)

Example fix

// before
let module = device.create_shader_module(wgpu::util::make_spirv_raw(
    include_bytes!("shader.wgsl"),
));
// after
let module = device.create_shader_module(wgpu::ShaderModuleDescriptor {
    label: Some("shader"),
    source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});
Defensive patterns

Strategy: validation

Validate before calling

fn is_binary_spirv(bytes: &[u8]) -> bool {
    bytes.len() >= 4 && bytes[..4] == [0x03, 0x02, 0x23, 0x07]
}
if !is_binary_spirv(&shader_bytes) {
    panic!("not a binary SPIR-V file — did you mean to use ShaderSource::Wgsl?");
}

Type guard

fn is_binary_spirv(bytes: &[u8]) -> bool {
    bytes.len() >= 4 && u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) == 0x07230203
}

Prevention

When it happens

Trigger: Calling `util::make_spirv_raw(bytes)` or `util::make_spirv_const(words/bytes)` with a slice whose first 4 bytes are not the little/big-endian SPIR-V magic word 0x07230203 — e.g. passing WGSL/GLSL source text, a JSON/spvasm disassembly, or a wrongly-encoded buffer.

Common situations: Loading a shader from disk but pointing at a .wgsl or .spvasm file instead of a compiled .spv; compiling GLSL to SPIR-V with text output enabled; a build script failing silently so a placeholder or empty file is embedded; byte-order/encoding mangling when embedding shaders in firmware or via include_bytes of the wrong artifact.

Related errors


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