gfx-rs/wgpu · error
Unexpected min({:?})
Error message
Unexpected min({:?}) What it means
The SPIR-V backend lowers MathFunction::Min through GlslStd450 FMin/SMin/UMin based on arg_scalar_kind; a Float/Sint/Uint argument is fine, but any other kind (None, Bool, etc.) reaches `unimplemented!("Unexpected min({:?})", other)`. The panic occurs in cache_expression_value invoked by write_block, halting shader translation.
Source
Thrown at naga/src/back/spv/block.rs:1406
MathOp::Ext(spirv::GlslStd450Op::FAbs)
}
Some(crate::ScalarKind::Sint) => MathOp::Ext(spirv::GlslStd450Op::SAbs),
Some(crate::ScalarKind::Uint) => {
MathOp::Custom(Instruction::unary(
spirv::Op::CopyObject, // do nothing
result_type_id,
id,
arg0_id,
))
}
other => unimplemented!("Unexpected abs({:?})", other),
}
}
Mf::Min => MathOp::Ext(match arg_scalar_kind {
Some(crate::ScalarKind::Float) => spirv::GlslStd450Op::FMin,
Some(crate::ScalarKind::Sint) => spirv::GlslStd450Op::SMin,
Some(crate::ScalarKind::Uint) => spirv::GlslStd450Op::UMin,
other => unimplemented!("Unexpected min({:?})", other),
}),
Mf::Max => MathOp::Ext(match arg_scalar_kind {
Some(crate::ScalarKind::Float) => spirv::GlslStd450Op::FMax,
Some(crate::ScalarKind::Sint) => spirv::GlslStd450Op::SMax,
Some(crate::ScalarKind::Uint) => spirv::GlslStd450Op::UMax,
other => unimplemented!("Unexpected max({:?})", other),
}),
Mf::Clamp => match arg_scalar_kind {
// Clamp is undefined if min > max. In practice this means it can use a median-of-three
// instruction to determine the value. This is fine according to the WGSL spec for float
// clamp, but integer clamp _must_ use min-max. As such we write out min/max.
Some(crate::ScalarKind::Float) => MathOp::Ext(spirv::GlslStd450Op::FClamp),
Some(_) => {
let (min_op, max_op) = match arg_scalar_kind {
Some(crate::ScalarKind::Sint) => {
(spirv::GlslStd450Op::SMin, spirv::GlslStd450Op::SMax)
}
Some(crate::ScalarKind::Uint) => {View on GitHub (pinned to 3e11ff59bf)
Solutions
- Use min only on numeric scalar/vector arguments in the shader
- Run naga validation before the spv backend to catch the bad call early
- Inspect the IR dump to locate the offending min expression
- Report a reproducer upstream if valid input panics
Example fix
// before let m = min(a, b); // a,b: bool // after let m = min(a.x, b.x); // f32 components
Defensive patterns
Strategy: validation
Validate before calling
assert!(matches!(arg_scalar_kind, Some(crate::ScalarKind::Float | crate::ScalarKind::Sint | crate::ScalarKind::Uint)), "min() requires numeric argument");
Type guard
fn min_max_supported(kind: Option<crate::ScalarKind>) -> bool {
matches!(kind, Some(crate::ScalarKind::Float | crate::ScalarKind::Sint | crate::ScalarKind::Uint))
} Prevention
- Use min only on numeric scalars/vectors
- Run naga validation before spv-out
- Test math built-ins against the WGSL spec's supported parameterizations
When it happens
Trigger: A `min(a, b)` built-in whose argument scalar kind is not Float, Sint, or Uint — e.g. min over bools or a kindless/composite type — while generating SPIR-V.
Common situations: Direct backend use on unvalidated/fuzzed IR; front-end regression letting invalid min() through; WGSL sources with min on booleans that should have failed validation.
Related errors
- Unexpected abs({:?})
- Unexpected max({:?})
- not implemented
- metal does not support vertex ray hit return
- not implemented
AI-assisted analysis of gfx-rs/wgpu@3e11ff59bf (2026-09-03).
Data as JSON: /api/errors/83e06051bacda542.
Report an issue: GitHub.