{"record":{"id":"5eb6d5330f474ed7","repo":"swc-project/swc","slug":"unable-to-access-unknown-nodes-5eb6d5","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/mod.rs","lineNumber":88,"sourceCode":"\n    pub fn mark_diagnostic<T: Into<Cow<'static, str>>>(&mut self, message: T, range: Span) {\n        self.diagnostics.push(DtsIssue {\n            message: message.into(),\n            range: SourceRange {\n                filename: self.filename.clone(),\n                span: range,\n            },\n        })\n    }\n}\n\nimpl FastDts {\n    pub fn transform(&mut self, program: &mut Program) -> Vec<DtsIssue> {\n        match program {\n            Program::Module(module) => self.transform_module_body(&mut module.body, false),\n            Program::Script(script) => self.transform_script(script),\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        }\n        take(&mut self.diagnostics)\n    }\n\n    fn transform_module_body(\n        &mut self,\n        items: &mut Vec<ModuleItem>,\n        in_global_or_lit_module: bool,\n    ) {\n        // 1. Analyze usage\n        self.used_refs.extend(TypeUsageAnalyzer::analyze(\n            items,\n            self.internal_annotations.as_ref(),\n        ));\n\n        // 2. Transform.\n        Self::remove_function_overloads_in_module(items);\n        self.transform_module_items(items);","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_typescript/src/fast_dts/mod.rs#L70-L106","documentation":"This is the entry point FastDts::transform (crates/swc_typescript/src/fast_dts/mod.rs:87): it dispatches on the Program, handling Program::Module and Program::Script. In builds compiled with `--cfg swc_ast_unknown`, swc_ecma_ast's decoder can yield an `Unknown(tag, value)` top-level program when the serialized payload's node tag is not recognized by this build, and the catch-all arm panics with \"unable to access unknown nodes\". Hitting this particular site means even the root node is foreign — the whole payload was written by a different swc_ecma_ast version.","triggerScenarios":"FastDts::transform is called on a Program deserialized (serde/cbor/plugin boundary) from a payload whose root program representation differs from what this build of swc_ecma_ast defines — e.g. a payload from a newer or incompatible swc release.","commonSituations":"Swc wasm plugins receive serialized AST from the host (the plugin fixture .cargo/config.toml sets `--cfg=swc_ast_unknown` exactly for this); CI matrix jobs compile with RUSTFLAGS=\"--cfg swc_ast_unknown\" and check cross-version behavior; custom tooling that persists Programs to disk and reloads them after an upgrade.","solutions":["Pin and align the single swc_core version used by both the AST producer and the swc_typescript consumer; verify with `cargo tree -i swc_ecma_ast` that only one version resolves.","Upgrade the consumer (swc_typescript/swc_core/@swc/core) to at least the producer's version so the root Program decodes concretely.","Re-parse from source with the same build's swc_ecma_parser instead of deserializing foreign payloads.","Version-stamp serialized ASTs and reject/fall back to re-parse when the stamp does not match the current swc_ecma_ast version."],"exampleFix":"// before: blindly decode any payload into a Program\nlet program: Program = deserialize(bytes)?;\nlet issues = dts.transform(&mut program);\n\n// after: gate on the payload's swc version before decoding\nlet header = read_swc_version(&bytes);\nif header != current_ast_version() {\n    return Err(format!(\"AST payload from {header} cannot feed this build\"));\n}\nlet mut program: Program = deserialize(bytes)?;\nlet issues = dts.transform(&mut program);","handlingStrategy":"validation","validationCode":"// Gate the deserialization boundary, not the transform:\nfn try_decode_program(bytes: &[u8]) -> Result<Program, String> {\n    let producer = read_embedded_swc_version(bytes)?;\n    if producer != compiled_ast_version() {\n        return Err(format!(\"AST payload from swc {producer} cannot feed this build\"));\n    }\n    decode(bytes).map_err(|e| e.to_string())\n}\n// compiled_ast_version(): record env!(\"CARGO_PKG_VERSION\") of swc_ecma_ast at build time.","typeGuard":"#[cfg(swc_ast_unknown)]\nfn program_is_known(p: &Program) -> bool {\n    !matches!(p, Program::Unknown(..))\n}","tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\nlet issues = catch_unwind(AssertUnwindSafe(|| dts.transform(&mut program)))\n    .map_err(|p| p.downcast_ref::<&str>().map(|s| s.to_string()).unwrap_or_default())?;","preventionTips":["Stamp every serialized AST with the producing swc_ecma_ast version and validate it before decode.","Keep exactly one swc_ecma_ast version in the dependency graph (`cargo tree -i swc_ecma_ast`).","Re-parse from source as the fallback whenever version metadata is missing or mismatched."],"tags":["swc","fast-dts","unknown-ast-node","version-mismatch","panic","program","entry-point"],"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"}