{"record":{"id":"113ffd7c19780cff","repo":"swc-project/swc","slug":"unable-to-access-unknown-nodes-113ffd","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/class.rs","lineNumber":299,"sourceCode":"            );\n        }\n    }\n\n    pub(crate) fn transform_constructor_params(\n        &mut self,\n        params: &mut [ParamOrTsParamProp],\n        private_constructor: bool,\n    ) -> Vec<ClassMember> {\n        let mut is_required = false;\n        let mut private_properties = Vec::new();\n        for param in params.iter_mut().rev() {\n            match param {\n                ParamOrTsParamProp::TsParamProp(ts_param_prop) => {\n                    is_required |= match &ts_param_prop.param {\n                        TsParamPropParam::Ident(binding_ident) => !binding_ident.optional,\n                        TsParamPropParam::Assign(_) => false,\n                        #[cfg(swc_ast_unknown)]\n                        _ => panic!(\"unable to access unknown nodes\"),\n                    };\n                    if let Some(private_prop) =\n                        self.transform_constructor_ts_param(ts_param_prop, is_required)\n                    {\n                        private_properties.push(private_prop);\n                    }\n                    ts_param_prop.readonly = false;\n                    ts_param_prop.accessibility = None;\n                }\n                ParamOrTsParamProp::Param(param) => {\n                    if private_constructor {\n                        continue;\n                    }\n\n                    self.transform_fn_param(param, is_required);\n                    is_required |= match &param.pat {\n                        Pat::Ident(binding_ident) => !binding_ident.optional,\n                        Pat::Array(array_pat) => !array_pat.optional,","sourceCodeStart":281,"sourceCodeEnd":317,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_typescript/src/fast_dts/class.rs#L281-L317","documentation":"fast_dts in swc_typescript (a port of oxc's fast-dts .d.ts emitter) matches exhaustively on SWC AST enums. When compiled with the swc_ast_unknown cfg — set for wasm plugin builds via `--cfg=swc_ast_unknown` in the .cargo/config.toml generated by `swc plugin new` — those enums gain an Unknown(tag, payload) variant carrying node kinds this swc_core version does not know. This arm matches TsParamPropParam (Ident/Assign) while computing is_required for constructor parameter properties and panics because the unknown node cannot be inspected.","triggerScenarios":"Running fast_dts over a Program whose constructor has a parameter property (e.g. `constructor(private x)` or `constructor(private x = 1)`) where the TsParamPropParam was deserialized as Unknown — typically a plugin built with --cfg=swc_ast_unknown receiving an AST from a newer host @swc/core than its pinned swc_core.","commonSituations":"Version skew between the running @swc/core host and the plugin's swc_core dependency; rebuilding a plugin against an older swc_core; new AST variants added to swc_ecma_ast in newer SWC releases reaching older plugins.","solutions":["Rebuild the plugin with the swc_core version that matches the host @swc/core (check @swc/core's bundled swc_core)","Bump swc_core in the plugin's Cargo.toml to the latest release so the new node kinds decode as concrete variants","Pre-scan the Program for Unknown nodes and skip fast_dts (or skip the file) when any are found","Pin the host SWC to a version whose AST the plugin understands until the plugin is rebuilt"],"exampleFix":"# before (plugin Cargo.toml)\nswc_core = { version = \"=16.x\", features = [\"ecma_plugin_transform\"] }\n# host @swc/core ships newer swc_ecma_ast -> TsParamPropParam::Unknown -> panic\n\n# after\nswc_core = { version = \"=latest-matching-host\", features = [\"ecma_plugin_transform\"] }\n# node kind now decodes to Ident/Assign; match succeeds","handlingStrategy":"type-guard","validationCode":"#[cfg(swc_ast_unknown)]\nfn ctor_params_contain_unknown(c: &swc_ecma_ast::Class) -> bool {\n    use swc_ecma_ast::*;\n    c.body.iter().any(|m| matches!(m, ClassMember::Constructor(ctor) if\n        ctor.params.iter().any(|p| matches!(p,\n            ParamOrTsParamProp::Unknown(..)\n                | ParamOrTsParamProp::TsParamProp(tp) if matches!(tp.param,\n                    TsParamPropParam::Unknown(..))))))\n}\n// skip fast_dts for classes failing this check","typeGuard":"#[cfg(swc_ast_unknown)]\nfn ts_param_prop_param_is_unknown(p: &swc_ecma_ast::TsParamPropParam) -> bool {\n    matches!(p, swc_ecma_ast::TsParamPropParam::Unknown(..))\n}","tryCatchPattern":"let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    run_fast_dts(&mut program) // your fast_dts invocation\n}));\nif out.is_err() {\n    // unknown AST node: emit a diagnostic and skip .d.ts for this file\n    handler.struct_err(\"fast_dts skipped: AST contains unknown nodes (plugin/host version mismatch)\").emit();\n}","preventionTips":["Pin the plugin's swc_core to the version bundled with the host @swc/core","Rebuild plugin wasm whenever the host SWC is upgraded","Check `cargo tree -p swc_core` before releasing a plugin","Never set --cfg=swc_ast_unknown in native (non-wasm) builds"],"tags":["fast-dts","swc-plugin","wasm","version-skew","unknown-node","constructor","param-property"],"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"}