{"record":{"id":"5edbc65a7fd2a4e8","repo":"swc-project/swc","slug":"unable-to-access-unknown-nodes-5edbc6","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_typescript/src/fast_dts/util/ast_ext.rs","lineNumber":87,"sourceCode":"    fn set_type_ann(&mut self, type_anno: Option<Box<TsTypeAnn>>);\n    fn bound_names<F: FnMut(&BindingIdent)>(&self, f: &mut F);\n}\n\nimpl PatExt for Pat {\n    fn get_type_ann(&self) -> &Option<Box<TsTypeAnn>> {\n        let pat = match self {\n            Pat::Assign(assign_pat) => &assign_pat.left,\n            _ => self,\n        };\n\n        match pat {\n            Pat::Ident(binding_ident) => &binding_ident.type_ann,\n            Pat::Array(array_pat) => &array_pat.type_ann,\n            Pat::Rest(rest_pat) => &rest_pat.type_ann,\n            Pat::Object(object_pat) => &object_pat.type_ann,\n            Pat::Assign(_) | Pat::Invalid(_) | Pat::Expr(_) => &None,\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        }\n    }\n\n    fn set_type_ann(&mut self, type_anno: Option<Box<TsTypeAnn>>) {\n        let pat = match self {\n            Pat::Assign(assign_pat) => &mut assign_pat.left,\n            _ => self,\n        };\n\n        match pat {\n            Pat::Ident(binding_ident) => binding_ident.type_ann = type_anno,\n            Pat::Array(array_pat) => array_pat.type_ann = type_anno,\n            Pat::Rest(rest_pat) => rest_pat.type_ann = type_anno,\n            Pat::Object(object_pat) => object_pat.type_ann = type_anno,\n            Pat::Assign(_) | Pat::Invalid(_) | Pat::Expr(_) => {}\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        }","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_typescript/src/fast_dts/util/ast_ext.rs#L69-L105","documentation":"PatternExt::get_type_ann (crates/swc_typescript/src/fast_dts/util/ast_ext.rs) is the shared helper fast_dts uses to read a type annotation off any binding pattern (unwrapping Pat::Assign to its left side first). Under `--cfg swc_ast_unknown`, a pattern decoded as `Unknown(tag, value)` falls into the catch-all and panics, because there is no annotation field to read on an opaque node. It fires during many passes (parameter checks, declaration transforms), always on deserialized cross-version AST.","triggerScenarios":"Any FastDts pass reads a type annotation from a pattern node whose tag is unknown to this swc_ecma_ast build — e.g. a new binding-pattern variant from a newer swc release inside a deserialized Program.","commonSituations":"Plugin/host swc version skew; two swc_ecma_ast versions resolved in one binary; persisted AST inputs replayed after upgrading @swc/core or swc_cli.","solutions":["Unify on one swc_core version across producer and consumer and rebuild.","Upgrade swc_typescript/swc_core past the version that introduced the new pattern node.","Re-parse from source with the same build before FastDts::transform.","Keep --cfg swc_ast_unknown only in plugin/ABI-stability targets, and rebuild those whenever the producing side changes."],"exampleFix":"// before\nlet ty = pat.get_type_ann(); // panics on Pat::Unknown\n\n// after: reject foreign payloads before the transform\nassert_payload_version_matches(&bytes)?;\nlet ty = pat.get_type_ann();","handlingStrategy":"type-guard","validationCode":"// Before any code path that calls get_type_ann on deserialized patterns:\n#[cfg(swc_ast_unknown)]\nfn safe_get_type_ann(p: &Pat) -> Option<&Option<Box<TsTypeAnn>>> {\n    if pat_is_known(p) { Some(p.get_type_ann_ref()) } else { None }\n}","typeGuard":"#[cfg(swc_ast_unknown)]\nfn pat_is_known(p: &Pat) -> bool {\n    !matches!(p, Pat::Unknown(..))\n}","tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\nlet issues = catch_unwind(AssertUnwindSafe(|| dts.transform(&mut program)))\n    .unwrap_or_else(|p| { tracing::error!(\"fast_dts rejected AST: {:?}\", p.downcast_ref::<&str>()); Vec::new() });","preventionTips":["Only pass Programs built by the same compiler instance to fast_dts.","Guard or reject deserialized patterns before invoking helper traits.","Align swc crate versions across the workspace."],"tags":["swc","fast-dts","unknown-ast-node","version-mismatch","panic","pat","type-annotation"],"backgroundTag":"ast-version-mismatch","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}