swc-project/swc · error

module string names unimplemented

Error message

module string names unimplemented

What it means

When swc_bundler collects export metadata for a module (crates/swc_bundler/src/bundler/export.rs), it builds internal Specifier records. For `export * as ns from './mod'` it handles only identifier names; a string namespace name (`export * as "ns" from './mod'`, ModuleExportName::Str) reaches unimplemented!() at export.rs:229 and panics. This is a known capability gap: the bundler predates ES2022 arbitrary module namespace names.

Source

Thrown at crates/swc_bundler/src/bundler/export.rs:229

                    .info
                    .items
                    .entry(named.src.clone().map(|v| *v))
                    .or_default();
                for s in &mut named.specifiers {
                    match s {
                        ExportSpecifier::Namespace(n) => {
                            match &mut n.name {
                                ModuleExportName::Ident(name) => {
                                    name.ctxt = self.export_ctxt;

                                    need_wrapping = true;
                                    v.push(Specifier::Namespace {
                                        local: name.clone().into(),
                                        all: true,
                                    })
                                }
                                ModuleExportName::Str(..) => {
                                    unimplemented!("module string names unimplemented")
                                }
                                #[cfg(swc_ast_unknown)]
                                _ => panic!("unable to access unknown nodes"),
                            };
                        }
                        ExportSpecifier::Default(d) => {
                            v.push(Specifier::Specific {
                                local: d.exported.clone().into(),
                                alias: Some(Id::new(atom!("default"), SyntaxContext::empty())),
                            });
                        }
                        ExportSpecifier::Named(n) => {
                            let orig = match &mut n.orig {
                                ModuleExportName::Ident(ident) => ident,
                                ModuleExportName::Str(..) => {
                                    unimplemented!("module string names unimplemented")
                                }
                                #[cfg(swc_ast_unknown)]

View on GitHub (pinned to d7d7434666)

Solutions

  1. Replace the string alias with a valid identifier: `export * as "my-ns" from './lib'` -> `export * as myNs from './lib'`.
  2. Grep the graph (including node_modules) for `export * as "` and patch the offending file or dependency.
  3. Add a pre-bundling SWC pass that rewrites string namespace aliases to identifiers.
  4. Track upstream swc_bundler support for module string names; until then externalize or pre-bundle that module with another tool.

Example fix

// before
export * as "my-ns" from './lib';

// after
export * as myNs from './lib';
Defensive patterns

Strategy: validation

Validate before calling

// Reject `export * as "str" from` before bundling
use swc_ecma_ast::{ExportSpecifier, ModuleDecl, ModuleExportName, ModuleItem};
for item in &module.body {
    if let ModuleItem::ModuleDecl(ModuleDecl::ExportNamedDecl(d)) = item {
        if let Some(specifiers) = d.decl.as_ref().and_then(|_| None).or(match &d.specifiers { s if !s.is_empty() => Some(s), _ => None }) {
            for s in specifiers {
                if let ExportSpecifier::Namespace(ns) = s {
                    if matches!(ns.name, ModuleExportName::Str(_)) {
                        anyhow::bail!("string namespace alias not supported by swc_bundler");
                    }
                }
            }
        }
    }
}

Type guard

fn has_string_namespace_reexport(m: &swc_ecma_ast::Module) -> bool {
    use swc_ecma_ast::*;
    m.body.iter().any(|i| matches!(i,
        ModuleItem::ModuleDecl(ModuleDecl::ExportNamedDecl(d))
            if d.specifiers.iter().any(|s| matches!(s,
                ExportSpecifier::Namespace(ns) if matches!(ns.name, ModuleExportName::Str(_))))))
}

Try / catch

match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| bundler.bundle(part)?)) {
    Ok(r) => r,
    Err(p) if p.downcast_ref::<&str>().map_or(false, |m| m.contains("module string names")) => {
        anyhow::bail!("rewrite `export * as \"ns\" from` to an identifier alias before bundling")
    }
    Err(p) => std::panic::resume_unwind(p),
}

Prevention

When it happens

Trigger: A module in the bundle graph contains `export * as "name with spaces" from './lib'` (or any string alias on a namespace re-export). During export collection ExportSpecifier::Namespace matches n.name = ModuleExportName::Str and the panic fires.

Common situations: Index/barrel files re-exporting namespaces under marketing names or names with dashes; code produced by code generators; third-party dependencies shipping ES2022 re-exports. Anything downstream of swc_bundler (spack-style tools, custom Rust pipelines) hits it.

Related errors


AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16). Data as JSON: /api/errors/6453cc699693b85e. Report an issue: GitHub.