wasmerio/wasmer · critical

Unhandled internal variant

Error message

Unhandled internal variant

What it means

In the LLVM backend's translator, the i32x4.extadd_pairwise_i16x8 implementation uses a match over operators to pick a sign/zero extension closure; any other operator reaching this match is an internal invariant violation, so it panics with "Unhandled internal variant". This means the dispatcher passed an operator the SIMD helper was never written to receive.

Source

Thrown at lib/compiler-llvm/src/translator/code.rs:4080

                let ((v1, i1), (v2, i2)) = self.state.pop2_extra()?;
                let (v1, _) = self.v128_into_i32x4(v1, i1)?;
                let (v2, _) = self.v128_into_i32x4(v2, i2)?;
                let res = err!(self.builder.build_int_add(v1, v2, ""));
                let res = err!(
                    self.builder
                        .build_bit_cast(res, self.intrinsics.i128_ty, "")
                );
                self.state.push1(res);
            }
            Operator::I32x4ExtAddPairwiseI16x8S | Operator::I32x4ExtAddPairwiseI16x8U => {
                let extend_op = match op {
                    Operator::I32x4ExtAddPairwiseI16x8S => {
                        |s: &Self, v| s.builder.build_int_s_extend(v, s.intrinsics.i32x4_ty, "")
                    }
                    Operator::I32x4ExtAddPairwiseI16x8U => {
                        |s: &Self, v| s.builder.build_int_z_extend(v, s.intrinsics.i32x4_ty, "")
                    }
                    _ => unreachable!("Unhandled internal variant"),
                };
                let (v, i) = self.state.pop1_extra()?;
                let (v, _) = self.v128_into_i16x8(v, i)?;

                let left = err!(self.builder.build_shuffle_vector(
                    v,
                    v.get_type().get_undef(),
                    VectorType::const_vector(&[
                        self.intrinsics.i32_consts[0],
                        self.intrinsics.i32_consts[2],
                        self.intrinsics.i32_consts[4],
                        self.intrinsics.i32_consts[6],
                    ]),
                    "",
                ));
                let left = err!(extend_op(self, left));
                let right = err!(self.builder.build_shuffle_vector(
                    v,

View on GitHub (pinned to 8c4b9ee9d3)

Solutions

  1. Retry compilation with a different backend (Cranelift or singlepass) if available.
  2. Check your wasmer version for known LLVM-backend SIMD bugs and upgrade.
  3. Avoid or polyfill the extadd_pairwise SIMD instructions if stuck on an affected version.
  4. Report a bug with the failing module; the unreachable! marks a translator invariant break.

Example fix

// before
wasmer compile module.wasm --llvm
// after
wasmer compile module.wasm --cranelift  // workaround for LLVM SIMD translator bug
Defensive patterns

Strategy: fallback

Try / catch

// Compilation aborts via panic; isolate compilation in a worker process
let out = std::process::Command::new("wasmer").args(["compile", "--cranelift", "module.wasm"]).status();

Prevention

When it happens

Trigger: Compiling a WASM module containing i32x4.extadd_pairwise_i16x8_s/u SIMD instructions (via translate_operator -> translate_integer_arithmetic_operator) with the LLVM compiler, when an internal refactor lets an unexpected Operator variant fall through.

Common situations: Running modules using the SIMD extended-pairwise-add proposal on the LLVM backend; usually a backend bug after code changes rather than a user mistake.

Related errors


AI-assisted analysis of wasmerio/wasmer@8c4b9ee9d3 (2026-09-01). Data as JSON: /api/errors/35b29fd44e667719. Report an issue: GitHub.