{"record":{"id":"b0d3bcd5e3e6e837","repo":"swc-project/swc","slug":"module-string-names-unimplemented-b0d3bc","errorCode":null,"errorMessage":"module string names unimplemented","messagePattern":"module string names unimplemented","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_bundler/src/bundler/keywords.rs","lineNumber":63,"sourceCode":"        c.class.visit_mut_with(self);\n        if let Some(renamed) = self.renamed(&c.ident) {\n            c.ident = renamed;\n        }\n    }\n\n    fn visit_mut_class_prop(&mut self, n: &mut ClassProp) {\n        if n.key.is_computed() {\n            n.key.visit_mut_with(self);\n        }\n\n        n.decorators.visit_mut_with(self);\n        n.value.visit_mut_with(self);\n    }\n\n    fn visit_mut_export_named_specifier(&mut self, n: &mut ExportNamedSpecifier) {\n        let orig = match &n.orig {\n            ModuleExportName::Ident(ident) => ident,\n            ModuleExportName::Str(..) => unimplemented!(\"module string names unimplemented\"),\n            #[cfg(swc_ast_unknown)]\n            _ => panic!(\"unable to access unknown nodes\"),\n        };\n        if let Some(renamed) = self.renamed(orig) {\n            n.orig = ModuleExportName::Ident(renamed);\n        }\n    }\n\n    fn visit_mut_expr(&mut self, n: &mut Expr) {\n        if let Expr::Ident(n) = n {\n            if let Some(renamed) = self.renamed(n) {\n                *n = renamed;\n            }\n            return;\n        }\n\n        n.visit_mut_children_with(self);\n    }","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/swc_bundler/src/bundler/keywords.rs#L45-L81","documentation":"swc_bundler renames identifiers that collide with contextual keywords before merging (keywords.rs). Its visit_mut_export_named_specifier only handles identifier origs; `export { \"a\" as b }` (ModuleExportName::Str) reaches unimplemented!() at keywords.rs:63 because there is no Ident to rename. The panic aborts the bundle.","triggerScenarios":"A module in the graph contains `export { \"string\" as alias };` (or the re-export form) and enters the keyword-rename pass; matching on n.orig hits Str and panics.","commonSituations":"Bundling code that exports names colliding with keywords via string aliases; generated code using string origs; failures that occur even when no keyword collision exists, because the match arms are evaluated for every named export.","solutions":["Replace the string orig with the identifier it refers to at the definition site and re-export normally.","Introduce a shim with identifier bindings for the string-named exports and import from the shim.","Scan sources and dependencies for `export { \"` / `as \"` patterns and normalize them.","Pre-transform the graph with a custom SWC pass before handing it to the bundler."],"exampleFix":"// before\nexport { \"default\" as def } from './mod';\n\n// after\nexport { default as def } from './mod';","handlingStrategy":"validation","validationCode":"// Same universal screen: any ModuleExportName::Str anywhere dooms the bundle\nuse swc_ecma_visit::{Visit, VisitWith};\nuse swc_ecma_ast::ModuleExportName;\nstruct AnyStr(pub bool);\nimpl Visit for AnyStr {\n    fn visit_module_export_name(&mut self, n: &ModuleExportName) {\n        if matches!(n, ModuleExportName::Str(_)) { self.0 = true; }\n        n.visit_children_with(self);\n    }\n}\nlet mut v = AnyStr(false);\nm.visit_with(&mut v);\nanyhow::ensure!(!v.0, \"keyword-rename pass will panic on string module names\");","typeGuard":"fn keyword_pass_safe(m: &swc_ecma_ast::Module) -> bool {\n    use swc_ecma_visit::{Visit, VisitWith};\n    use swc_ecma_ast::ModuleExportName;\n    struct F(bool); impl Visit for F {\n        fn visit_module_export_name(&mut self, n: &ModuleExportName) {\n            if matches!(n, ModuleExportName::Str(_)) { self.0 = false; }\n            n.visit_children_with(self);\n        }\n    }\n    let mut f = F(true); m.visit_with(&mut f); f.0\n}","tryCatchPattern":"match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| bundler.bundle(part)?)) {\n    Ok(v) => v,\n    Err(p) if format!(\"{:?}\", &p).contains(\"module string names\") =>\n        Err(anyhow::anyhow!(\"string module name hit keyword-rename; normalize to identifiers\")),\n    Err(p) => std::panic::resume_unwind(p),\n}","preventionTips":["The keyword-rename pass visits every named export regardless of actual keyword collisions — the only prevention is zero string names in the graph.","Automate normalization (string -> ident) as the last step of any codegen pipeline feeding the bundler.","Review vendor patches for quoted export names.","Keep the universal Str-name screen in the loader."],"tags":["swc","bundler","esm","es2022","module-string-names","panic","keyword-rename"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}