{"record":{"id":"605c09d4ef657031","repo":"wasmerio/wasmer","slug":"can-t-form-extrainfo-with-two-pending-canonicaliza","errorCode":null,"errorMessage":"Can't form ExtraInfo with two pending canonicalization","messagePattern":"Can't form ExtraInfo with two pending canonicalization","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/compiler-llvm/src/translator/state.rs","lineNumber":213,"sourceCode":"        debug_assert!(\n            self.has_pending_f64_nan() == other.has_pending_f64_nan()\n                || self.is_arithmetic_f64()\n                || other.is_arithmetic_f64()\n        );\n        let info = match (\n            self.is_arithmetic_f32() && other.is_arithmetic_f32(),\n            self.is_arithmetic_f64() && other.is_arithmetic_f64(),\n        ) {\n            (false, false) => Default::default(),\n            (true, false) => ExtraInfo::arithmetic_f32(),\n            (false, true) => ExtraInfo::arithmetic_f64(),\n            (true, true) => (ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64())?,\n        };\n        match (self.has_pending_f32_nan(), self.has_pending_f64_nan()) {\n            (false, false) => Ok(info),\n            (true, false) => info | ExtraInfo::pending_f32_nan(),\n            (false, true) => info | ExtraInfo::pending_f64_nan(),\n            (true, true) => unreachable!(\"Can't form ExtraInfo with two pending canonicalization\"),\n        }\n    }\n}\n\n#[derive(Debug, Clone, Copy)]\npub struct TagCatchInfo<'ctx> {\n    pub tag: u32,\n    // The catch block\n    pub catch_block: BasicBlock<'ctx>,\n    // The PHI node to receive the exnref, if needed; catch_all\n    // blocks don't need the exnref.\n    pub exnref_phi: Option<PhiValue<'ctx>>,\n}\n\n#[derive(Debug)]\npub struct Landingpad<'ctx> {\n    // The block that has the landingpad instruction.\n    // Will be None for catch-less try_table instructions","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/wasmerio/wasmer/blob/8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5/lib/compiler-llvm/src/translator/state.rs#L195-L231","documentation":"This panic occurs in `ExtraInfo`'s `bitand` implementation in wasmtime's LLVM backend state tracking. `ExtraInfo` can carry at most one pending NaN canonicalization flag (pending f32 or pending f64); when combining two infos that both have pending NaN flags, the `(true, true)` arm deliberately panics because the struct cannot represent two pending canonicalizations at once. It is an internal invariant violation in floating-point NaN legalization bookkeeping.","triggerScenarios":"Chaining floating-point LLVM operations (via `and` on `ExtraInfo`) where both operands produced a pending NaN canonicalization — e.g. `ExtraInfo::arithmetic_f32() | ExtraInfo::arithmetic_f64()` combined with state that already has both `has_pending_f32_nan()` and `has_pending_f64_nan()` set.","commonSituations":"Running wasm with unusual NaN-heavy float code through the LLVM backend; enabling `wasm_nan_canonicalization` (or backends where it is default) on versions with bookkeeping bugs; modules mixing f32/f64 NaN-producing ops in patterns the tracker didn't expect.","solutions":["Upgrade wasmtime — NaN-canonicalization bookkeeping bugs are fixed over time","Disable NaN canonicalization: `Config::wasm_nan_canonicalization(false)` (accepting non-deterministic NaNs) if your workload tolerates it","Reduce the module with wasm-opt/NaN-transform passes so canonicalization is not needed at runtime","Check whether a custom LLVM build changes float instruction selection and try the stock toolchain","Report with a minimal f32/f64 module reproducing the double pending canonicalization"],"exampleFix":"// before\nlet mut config = Config::default();\nconfig.wasm_nan_canonicalization(true);\n// after\nlet mut config = Config::default();\nconfig.wasm_nan_canonicalization(false); // avoid the ExtraInfo invariant panic","handlingStrategy":"validation","validationCode":"let mut config = wasmtime::Config::default();\nconfig.wasm_nan_canonicalization(false); // skip the ExtraInfo NaN bookkeeping entirely if your workload tolerates it\nlet engine = Engine::new(&config)?;","typeGuard":null,"tryCatchPattern":"let module = std::panic::catch_unwind(|| Module::new(&engine, &bytes).map_err(|e| anyhow::anyhow!(e)))\n    .map_err(|_| anyhow::anyhow!(\"compiler panic\"))??;\n// on panic: retry with wasm_nan_canonicalization(false)","preventionTips":["If determinism is not required, leave wasm_nan_canonicalization disabled on older wasmtime","Upgrade wasmtime promptly; NaN bookkeeping fixes land regularly","Combine f32/f64-heavy modules under CI compile tests when enabling canonicalization","Compile modules off-thread so panics don't abort the host"],"tags":["wasmtime","llvm-backend","nan-canonicalization","panic","floating-point"],"backgroundTag":"nan-canonicalization-panic","analyzedSha":"8c4b9ee9d33fb2068863fbb3d328683e7e6ff7f5","analyzedAt":"2026-09-01T23:06:31.009Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}