wasmerio/wasmer · error
Unhandled inner case
Error message
Unhandled inner case
What it means
An explicit `unreachable!("Unhandled inner case")` panic inside `translate_conversion_operator` in wasmer's LLVM backend. For the SIMD `I64x2Extend*I32x4*` conversion operators the code builds a nested match to pick the extend closure (zero- vs sign-extend); if the outer match dispatched an operator the inner match does not enumerate, the inner wildcard at code.rs:8771 panics. This indicates an inconsistency between the outer operator dispatch and the inner operator refinement — reached only when a conversion operator's inner selection was not covered, usually due to a bug or a non-standard/new operator variant.
Source
Thrown at lib/compiler-llvm/src/translator/code.rs:8771
);
let res = err!(
self.builder
.build_bit_cast(res, self.intrinsics.i128_ty, "")
);
self.state.push1(res);
}
Operator::I64x2ExtendLowI32x4U
| Operator::I64x2ExtendLowI32x4S
| Operator::I64x2ExtendHighI32x4U
| Operator::I64x2ExtendHighI32x4S => {
let extend = match op {
Operator::I64x2ExtendLowI32x4U | Operator::I64x2ExtendHighI32x4U => {
|s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i64x2_ty, "")
}
Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendHighI32x4S => {
|s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i64x2_ty, "")
}
_ => unreachable!("Unhandled inner case"),
};
let indices = match op {
Operator::I64x2ExtendLowI32x4S | Operator::I64x2ExtendLowI32x4U => {
[self.intrinsics.i32_consts[0], self.intrinsics.i32_consts[1]]
}
Operator::I64x2ExtendHighI32x4S | Operator::I64x2ExtendHighI32x4U => {
[self.intrinsics.i32_consts[2], self.intrinsics.i32_consts[3]]
}
_ => unreachable!("Unhandled inner case"),
};
let (v, i) = self.state.pop1_extra()?;
let (v, _) = self.v128_into_i32x4(v, i)?;
let low = err!(self.builder.build_shuffle_vector(
v,
v.get_type().get_undef(),
VectorType::const_vector(&indices),
"",
));View on GitHub (pinned to 8c4b9ee9d3)
Solutions
- Use the Cranelift backend for this module instead of LLVM
- Upgrade wasmer and wasmer-compiler-llvm to a version covering the conversion operator
- Recompile the module without the offending SIMD conversion instructions (disable simd128/relaxed-simd)
- Validate the module with restrictive feature flags before compilation so this becomes a proper compile error
- If the operator is standard and present in upstream wasmer, file a bug with the module and wasmer version
Example fix
// before let engine = Engine::from(LLVM::new()); // after let engine = Engine::from(Cranelift::new());
Defensive patterns
Strategy: try-catch
Validate before calling
fn validate_before_compile(engine: &wasmer::Engine, wasm: &[u8]) -> Result<(), String> {
wasmer::Module::validate(engine, wasm)
.map_err(|e| format!("unsupported conversion op (SIMD extend?): {e}"))
} Type guard
fn has_simd_conversion_ops(wasm: &[u8]) -> bool {
// SIMD conversions use the 0xFD prefix opcode space
wasm.windows(2).any(|w| w[0] == 0xFD)
} Try / catch
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
wasmer::Module::new(&llvm_engine, &wasm)
}));
match result {
Ok(Ok(module)) => Ok(module),
Ok(Err(e)) => Err(e.into()),
Err(_) => {
log::warn("wasmer LLVM panic (unhandled conversion case); retrying with Cranelift");
wasmer::Module::new(&cranelift_engine, &wasm).map_err(Into::into)
}
} Prevention
- Validate modules with SIMD features off unless your wasmer+LLVM build supports them fully
- Run compilation in an isolated thread and translate panics into CompileError-like results
- Keep a Cranelift fallback engine for modules the LLVM backend cannot compile
- Upgrade wasmer when your wasm toolchain starts emitting newer SIMD conversion opcodes
- Add CI coverage compiling your real wasm artifacts with the exact production engine config
When it happens
Trigger: Compiling a Wasm module whose conversion operator (in this arm: I64x2ExtendLow/HighI32x4S/U family, or a neighboring SIMD conversion like f32x4/f64x2 converts) reaches translate_conversion_operator but falls into the inner `_` arm via `Module::new` with the LLVM backend.
Common situations: Newer toolchains emitting SIMD conversion or relaxed-simd conversion instructions unsupported by the installed wasmer version; LLVM backend selected for SIMD modules; hand-modified or fuzzed bytecode bypassing validation.
Related errors
- unimplemented operator {operator:?}
- global #{} is a constant
- Currently only SIMD instructions are mapped to their return
- only numeric types are supported in function signatures
- not a `sys` backend!
AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01).
Data as JSON: /api/errors/81f6479937cfd285.
Report an issue: GitHub.