{"record":{"id":"1100f73b6a8411ef","repo":"swc-project/swc","slug":"module-string-names-unimplemented-1100f7","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/load.rs","lineNumber":364,"sourceCode":"                let src = Source {\n                    is_loaded_synchronously: !is_dynamic,\n                    is_unconditional,\n                    module_id: id,\n                    local_ctxt: SyntaxContext::empty().apply_mark(local_mark),\n                    export_ctxt: SyntaxContext::empty().apply_mark(export_mark),\n                    src: *decl.src,\n                };\n                files.push((src.clone(), file_name));\n\n                // TODO: Handle rename\n                let mut specifiers = Vec::new();\n                for s in decl.specifiers {\n                    match s {\n                        ImportSpecifier::Named(s) => {\n                            let imported = match s.imported {\n                                Some(ModuleExportName::Ident(ident)) => Some(ident),\n                                Some(ModuleExportName::Str(..)) => {\n                                    unimplemented!(\"module string names unimplemented\")\n                                }\n                                _ => None,\n                            };\n                            specifiers.push(Specifier::Specific {\n                                local: s.local.into(),\n                                alias: imported.map(From::from),\n                            })\n                        }\n                        ImportSpecifier::Default(s) => specifiers.push(Specifier::Specific {\n                            local: s.local.into(),\n                            alias: Some(Id::new(atom!(\"default\"), SyntaxContext::empty())),\n                        }),\n                        ImportSpecifier::Namespace(s) => {\n                            specifiers.push(Specifier::Namespace {\n                                local: s.local.into(),\n                                all: forced_ns.contains(&src.src.value),\n                            });\n                        }","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/swc-project/swc/blob/d7d74346665e36e692aa07e13d4ee3ee692ee35c/crates/swc_bundler/src/bundler/load.rs#L346-L382","documentation":"When swc_bundler loads a module and records its imports for the dependency graph (load.rs:364), it converts ImportSpecifier::Named into its internal Specifier model. The `imported` field must resolve to an Id; a string name (`import { \"a\" as b } from './dep'`, ModuleExportName::Str) hits unimplemented!() and panics during load — earlier than most other string-name panics.","triggerScenarios":"Any entry or dependency module contains `import { \"string name\" as local } from './x';`. The panic occurs in the load phase while building the import specifier list, before chunking even starts.","commonSituations":"Bundling a project whose deps use string import names; first run of a bundling pipeline against a package that was previously only transpiled; error location points at load.rs, confusing users who expect later stages.","solutions":["Rewrite the import against an identifier export.","Patch the exporting dependency to also export an identifier alias, then import that.","Gate CI on a grep for `import { \"` across src and node_modules so this fails fast with a clear message.","Externalize the module or use a pre-bundle transform."],"exampleFix":"// before\nimport { \"legacy-key\" as key } from './dep';\n\n// after (dep adds: export const key = value;)\nimport { key } from './dep';","handlingStrategy":"validation","validationCode":"// load.rs panics earliest: gate inside your Load impl\nimpl Load for ScreenedLoader {\n    fn load(&self, f: &FileName) -> Result<ModuleRecord, anyhow::Error> {\n        let rec = self.inner.load(f)?;\n        let mut bad = StrImportScan::default();\n        rec.module.visit_with(&mut bad);\n        if bad.count > 0 {\n            anyhow::bail!(\"{} contains {} string import name(s); swc_bundler load() will panic\", f, bad.count);\n        }\n        Ok(rec)\n    }\n}","typeGuard":"fn load_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":"// Loading happens inside Bundler::bundle; catch_unwind around the whole bundle call\nlet res = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| bundler.bundle(part)?));\nif let Err(p) = res {\n    if format!(\"{:?}\", &p).contains(\"module string names\") {\n        anyhow::bail!(\"a module in the graph uses string import names; see loader screen logs\");\n    }\n    std::panic::resume_unwind(p);\n}","preventionTips":["Put the string-name screen in the Load implementation — it runs before the bundler's internal load() panic site.","Log the file path during screening so users know which module to fix.","Reject dependency versions that introduce string imports at audit time (grep the tarball).","Keep entry-point smoke bundles in CI."],"tags":["swc","bundler","esm","es2022","module-string-names","panic","module-loading","imports"],"backgroundTag":null,"analyzedSha":"d7d74346665e36e692aa07e13d4ee3ee692ee35c","analyzedAt":"2026-08-16T12:41:13.160Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}