gfx-rs/wgpu · error

Unexpected selector {:?}

Error message

Unexpected selector {:?}

What it means

The SPIR-V frontend (parser) only knows how to build a switch when the OpSwitch selector is an integer scalar (Sint/Uint). If the selector expression has any other type after loading (e.g. a vector or bool), the block builder panics with 'Unexpected selector'.

Source

Thrown at naga/src/front/spv/next_block.rs:2166

                        crate::TypeInner::Scalar(crate::Scalar {
                            kind: crate::ScalarKind::Uint,
                            width: _,
                        }) => {
                            // IR expects a signed integer, so do a bitcast
                            ctx.expressions.append(
                                crate::Expression::As {
                                    kind: crate::ScalarKind::Sint,
                                    expr: selector_handle,
                                    convert: None,
                                },
                                span,
                            )
                        }
                        crate::TypeInner::Scalar(crate::Scalar {
                            kind: crate::ScalarKind::Sint,
                            width: _,
                        }) => selector_handle,
                        ref other => unimplemented!("Unexpected selector {:?}", other),
                    };

                    // Clear past switch cases to prevent them from entering this one
                    self.switch_cases.clear();

                    for _ in 0..(inst.wc - 3) / 2 {
                        let literal = self.next()?;
                        let target = self.next()?;

                        let case_body_idx = ctx.bodies.len();

                        // Check if any previous case already used this target block id, if so
                        // group them together to reorder them later so that no weird
                        // fallthrough cases happen.
                        if let Some(&mut (_, ref mut literals)) = self.switch_cases.get_mut(&target)
                        {
                            literals.push(literal as i32);
                            continue;

View on GitHub (pinned to 3e11ff59bf)

Solutions

  1. Fix or regenerate the SPIR-V binary so the OpSwitch selector is a scalar integer (Sint/Uint) as the SPIR-V spec requires
  2. Run spirv-val (spirv-tools) on the binary to find the invalid OpSwitch and identify the producing tool
  3. If the source shader is yours, ensure the switch condition is a plain i32/u32 value in the source language
  4. Upgrade naga in case selector handling was extended

Example fix

// before (SPIR-V): %sel = op producing bool/vectors; OpSwitch %sel ...
// after: %sel_i32 = ... i32 selector; OpSwitch %sel_i32 %default %case0 %block0 ...
Defensive patterns

Strategy: validation

Validate before calling

// validate SPIR-V before parsing with naga:
// spirv-val module.spv  (rejects non-int OpSwitch selectors per spec)
if !spirv_val_ok(&bytes) { return Err("invalid SPIR-V: bad OpSwitch selector"); }

Try / catch

// naga frontend returns Err for most malformed input, but this case panics; validate with spirv-val first
match naga::front::spv::parse_u8_slice(&bytes, &options) { Ok(m) => ..., Err(e) => ... }

Prevention

When it happens

Trigger: Parsing a SPIR-V binary whose OpSwitch selector id resolves to a non-scalar-integer type — malformed or non-conformant SPIR-V, or output of a tool that produced an unexpected selector type.

Common situations: Loading shaders generated by custom/buggy compilers, fuzzed or hand-edited SPIR-V binaries, or SPIR-V produced after unusual constant folding that leaves a bool/vector selector.

Related errors


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