{"record":{"id":"5fed71f12d38f62f","repo":"swc-project/swc","slug":"unable-to-access-unknown-nodes-5fed71","errorCode":null,"errorMessage":"unable to access unknown nodes","messagePattern":"unable to access unknown nodes","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/babelify/operators.rs","lineNumber":68,"sourceCode":"            BinaryOp::LShift => BinaryOpOutput::BinOp(BinaryExprOp::LeftShift),\n            BinaryOp::RShift => BinaryOpOutput::BinOp(BinaryExprOp::RightShift),\n            BinaryOp::ZeroFillRShift => BinaryOpOutput::BinOp(BinaryExprOp::UnsignedRightShift),\n            BinaryOp::Add => BinaryOpOutput::BinOp(BinaryExprOp::Addition),\n            BinaryOp::Sub => BinaryOpOutput::BinOp(BinaryExprOp::Subtraction),\n            BinaryOp::Mul => BinaryOpOutput::BinOp(BinaryExprOp::Multiplication),\n            BinaryOp::Div => BinaryOpOutput::BinOp(BinaryExprOp::Division),\n            BinaryOp::Mod => BinaryOpOutput::BinOp(BinaryExprOp::Remainder),\n            BinaryOp::BitOr => BinaryOpOutput::BinOp(BinaryExprOp::Or),\n            BinaryOp::BitXor => BinaryOpOutput::BinOp(BinaryExprOp::Xor),\n            BinaryOp::BitAnd => BinaryOpOutput::BinOp(BinaryExprOp::And),\n            BinaryOp::LogicalOr => BinaryOpOutput::LogicOp(LogicalExprOp::Or),\n            BinaryOp::LogicalAnd => BinaryOpOutput::LogicOp(LogicalExprOp::And),\n            BinaryOp::In => BinaryOpOutput::BinOp(BinaryExprOp::In),\n            BinaryOp::InstanceOf => BinaryOpOutput::BinOp(BinaryExprOp::Instanceof),\n            BinaryOp::Exp => BinaryOpOutput::BinOp(BinaryExprOp::Exponentiation),\n            BinaryOp::NullishCoalescing => BinaryOpOutput::LogicOp(LogicalExprOp::Nullish),\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        }\n    }\n}\n\n// Babel appears to just store all of these as a string. See\n// AssignmentExpression.operator field. NOTE(dwoznick): I'm unsure if this is\n// the correct way to handle this case.\nimpl Babelify for AssignOp {\n    type Output = String;\n\n    fn babelify(self, _ctx: &Context) -> Self::Output {\n        match self {\n            AssignOp::Assign => \"=\".into(),\n            AssignOp::AddAssign => \"+=\".into(),\n            AssignOp::SubAssign => \"-=\".into(),\n            AssignOp::MulAssign => \"*=\".into(),\n            AssignOp::DivAssign => \"/=\".into(),\n            AssignOp::ModAssign => \"%=\".into(),","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/babelify/operators.rs#L50-L86","documentation":"This Babelify impl maps the unified SWC BinaryOp enum onto either a Babel BinaryExprOp or LogicalExprOp. The `#[cfg(swc_ast_unknown)]` wildcard arm is compiled only in builds that pass `--cfg=swc_ast_unknown` (the cfg SWC plugin builds use to make swc_ecma_ast enums non_exhaustive), and it panics if the operator value is a variant the linked swc_ecma_ast version does not define. As elsewhere, this signals that the AST was produced by a different swc version than the one compiled into the babelify call.","triggerScenarios":"Babelifying an expression whose BinaryOp variant arrived from a newer/older swc_ecma_ast — across a plugin ABI boundary, a mixed-version Cargo graph, or deserialized ASTs from another producer version.","commonSituations":"A new swc release adds an operator variant and older plugins/wasm binaries panic on ASTs from the upgraded host; duplicate swc_ecma_ast versions in the dependency tree; cached build artifacts surviving a swc upgrade.","solutions":["Align swc versions: `cargo tree -i swc_ecma_ast` must show one version; update through swc_core","Upgrade swc_estree_compat together with swc_ecma_ast so the new operator variant is mapped","Rebuild plugin/wasm binaries against the host's swc release after upgrading","Use catch_unwind around Program::babelify to fail per-file instead of aborting the process"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn binary_op_known(o: &BinaryOp) -> bool {\n    matches!(\n        o,\n        BinaryOp::Eq | BinaryOp::NotEq | BinaryOp::EqEqEq | BinaryOp::NotEqEq\n        | BinaryOp::Lt | BinaryOp::LtEq | BinaryOp::Gt | BinaryOp::GtEq\n        | BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div | BinaryOp::Mod\n        | BinaryOp::BitOr | BinaryOp::BitXor | BinaryOp::BitAnd\n        | BinaryOp::LogicalOr | BinaryOp::LogicalAnd\n        | BinaryOp::In | BinaryOp::InstanceOf | BinaryOp::Exp | BinaryOp::NullishCoalescing\n        | BinaryOp::LShift | BinaryOp::RShift | BinaryOp::ZeroFillRShift\n    )\n}","tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| program.babelify(&ctx)))\n    .map_err(|_| anyhow::anyhow!(\"babelify failed: swc_ecma_ast version mismatch (unknown BinaryOp)\"))?;","preventionTips":["Lock all swc crates to one version via swc_core and Cargo.lock","Fail CI on duplicate swc_ecma_ast versions in the graph","Rebuild cross-version boundaries (plugins, wasm) after host upgrades","Add operator-rich fixtures to babelify smoke tests"],"tags":["swc","babelify","panic","version-mismatch","non-exhaustive","binary-operator"],"backgroundTag":"ast-version-mismatch","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-22T20:17:22.307Z"}