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
- Fix or regenerate the SPIR-V binary so the OpSwitch selector is a scalar integer (Sint/Uint) as the SPIR-V spec requires
- Run spirv-val (spirv-tools) on the binary to find the invalid OpSwitch and identify the producing tool
- If the source shader is yours, ensure the switch condition is a plain i32/u32 value in the source language
- 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
- Always spirv-validate binaries before feeding them to naga
- Ensure upstream compilers emit i32/u32 OpSwitch selectors
- Avoid hand-editing SPIR-V
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
- not implemented
- Unexpected saturate({:?})
- Unexpected sign({:?})
- Unexpected firstLeadingBit({:?})
- Unexpected pointer expression {:?}
AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03).
Data as JSON: /api/errors/99afedbe9a2650de.
Report an issue: GitHub.