{"record":{"id":"9e801d581527ba17","repo":"swc-project/swc","slug":"unable-to-access-unknown-nodes-9e801d","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/inferrer.rs","lineNumber":28,"sourceCode":"    util::types::{ts_keyword_type, type_ann},\n    FastDts,\n};\n\nimpl FastDts {\n    pub(crate) fn infer_type_from_expr(&mut self, e: &Expr) -> Option<Box<TsType>> {\n        match e {\n            Expr::Ident(ident) if ident.sym.as_str() == \"undefined\" => {\n                Some(ts_keyword_type(TsKeywordTypeKind::TsUndefinedKeyword))\n            }\n            Expr::Lit(lit) => match lit {\n                Lit::Str(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsStringKeyword)),\n                Lit::Bool(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsBooleanKeyword)),\n                Lit::Num(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsNumberKeyword)),\n                Lit::BigInt(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsBigIntKeyword)),\n                Lit::Null(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsNullKeyword)),\n                Lit::Regex(_) | Lit::JSXText(_) => None,\n                #[cfg(swc_ast_unknown)]\n                _ => panic!(\"unable to access unknown nodes\"),\n            },\n            Expr::Tpl(_) => Some(ts_keyword_type(TsKeywordTypeKind::TsStringKeyword)),\n            Expr::Fn(fn_expr) => self.transform_fn_to_ts_type(\n                &fn_expr.function,\n                fn_expr.ident.as_ref().map(|ident| ident.span),\n            ),\n            Expr::Arrow(arrow_expr) => self.transform_arrow_expr_to_ts_type(arrow_expr),\n            Expr::Array(arr) => {\n                self.array_inferred(arr.span);\n                Some(ts_keyword_type(TsKeywordTypeKind::TsUnknownKeyword))\n            }\n            Expr::Object(obj) => self.transform_object_to_ts_type(obj, false),\n            Expr::Class(class) => {\n                self.inferred_type_of_class_expression(class.span());\n                Some(ts_keyword_type(TsKeywordTypeKind::TsUnknownKeyword))\n            }\n            Expr::Paren(expr) => self.infer_type_from_expr(&expr.expr),\n            Expr::TsNonNull(non_null) => self.infer_type_from_expr(&non_null.expr),","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_typescript/src/fast_dts/inferrer.rs#L10-L46","documentation":"infer_type_from_expr (crates/swc_typescript/src/fast_dts/inferrer.rs) infers a .d.ts type from expressions such as parameter defaults and exported initializers; for `Expr::Lit` it maps literal kinds to keyword types (string/bool/number/bigint/null). Under `--cfg swc_ast_unknown`, a literal kind this build does not recognize decodes to `Unknown(tag, value)` and the catch-all arm panics, since no keyword type can be derived from an opaque node. The root cause is always an AST produced by a different swc_ecma_ast version crossing a serialization boundary.","triggerScenarios":"FastDts infers a type from a default value or exported expression (e.g. `export const x = <newLiteralKind>`) whose literal node tag is unknown to this build — a Lit variant added in a newer swc_ecma_ast and deserialized into this older binary.","commonSituations":"Wasm plugins built against an older swc_core receiving AST from a newer @swc/core host; CI checks compiled with RUSTFLAGS=\"--cfg swc_ast_unknown\" exercising newer recorded fixtures; multi-process pipelines that hand serialized ASTs between binaries built at different times.","solutions":["Unify the swc_core/swc_ecma_ast version between the serializer and the swc_typescript build, then rebuild both.","Upgrade swc_typescript/swc_core so the new literal kind is known and maps to a real TsType instead of Unknown.","Re-parse source text in the same process before FastDts::transform rather than reusing a foreign AST.","Treat --cfg swc_ast_unknown builds as version-sensitive: rebuild/re-deploy them whenever the producing side is upgraded."],"exampleFix":"// before: two crates resolve different swc_ecma_ast versions\n# Cargo.toml\nswc_typescript = \"9\"\nswc_ecma_ast = \"0.118\"   # newer than what swc_typescript was built for\n\n// after: let swc_core drive every AST crate version\nswc_core = { version = \"=16.0.0\", features = [\"ecma_ast\", \"typescript\"] }","handlingStrategy":"type-guard","validationCode":"// Before inferring types from deserialized default values:\n#[cfg(swc_ast_unknown)]\nfn default_value_lits_known(params: &[Param]) -> bool {\n    params.iter().all(|p| match &p.pat {\n        Pat::Assign(a) => expr_lits_known(&a.right),\n        _ => true,\n    })\n}\n#[cfg(swc_ast_unknown)]\nfn expr_lits_known(e: &Expr) -> bool {\n    !matches!(e, Expr::Lit(l) if matches!(l, Lit::Unknown(..)))\n}","typeGuard":"#[cfg(swc_ast_unknown)]\nfn lit_is_known(l: &Lit) -> bool {\n    !matches!(l, Lit::Unknown(..))\n}","tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\nlet issues = catch_unwind(AssertUnwindSafe(|| dts.transform(&mut program)))\n    .map_err(|p| format!(\"fast_dts: {}\", p.downcast_ref::<&str>().unwrap_or(&\"panic\")))?;","preventionTips":["Align swc_core versions between AST serializer and consumer before running fast_dts on deserialized input.","In multi-process pipelines, ship both endpoints from the same build; never mix binaries from different release trains.","Re-parse from source when the incoming AST's provenance/version is unknown."],"tags":["swc","fast-dts","unknown-ast-node","version-mismatch","panic","type-inference","literal"],"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"}