rollup/rollup · error

not implemented: Cannot convert ModuleDecl::TsNamespaceExpor

Error message

not implemented: Cannot convert ModuleDecl::TsNamespaceExport

What it means

convert_module_declaration (converter.rs:566) has an unimplemented! arm at line 591 for ModuleDecl::TsNamespaceExport. This is TypeScript's `export as namespace Name` directive that exposes a module as a global. SWC parses it but the buffer format cannot represent it, so the converter panics and Rollup surfaces the message as a parse error.

Source

Thrown at rust/parse_ast/src/convert_ast/converter.rs:592

      }
      ModuleDecl::ExportNamed(export_named) => {
        self.convert_export_named_declaration(export_named, module_item_insert_position)
      }
      ModuleDecl::Import(import_declaration) => self.store_import_declaration(import_declaration),
      ModuleDecl::ExportDefaultExpr(export_default_expression) => self
        .convert_export_default_expression(export_default_expression, module_item_insert_position),
      ModuleDecl::ExportAll(export_all) => self.convert_export_all(export_all),
      ModuleDecl::ExportDefaultDecl(export_default_declaration) => self
        .convert_export_default_declaration(
          export_default_declaration,
          module_item_insert_position,
        ),
      ModuleDecl::TsImportEquals(_) => unimplemented!("Cannot convert ModuleDecl::TsImportEquals"),
      ModuleDecl::TsExportAssignment(_) => {
        unimplemented!("Cannot convert ModuleDecl::TsExportAssignment")
      }
      ModuleDecl::TsNamespaceExport(_) => {
        unimplemented!("Cannot convert ModuleDecl::TsNamespaceExport")
      }
    }
  }

  pub(crate) fn convert_module_export_name(&mut self, module_export_name: &ModuleExportName) {
    match module_export_name {
      ModuleExportName::Ident(identifier) => self.convert_identifier(identifier),
      ModuleExportName::Str(string_literal) => self.store_literal_string(string_literal),
    }
  }

  pub(crate) fn convert_module_item(
    &mut self,
    module_item: &ModuleItem,
    module_item_insert_position: &mut u32,
  ) {
    match module_item {
      ModuleItem::Stmt(statement) => self.convert_statement(statement),

View on GitHub (pinned to ddc4ffab62)

Solutions

  1. Add a TypeScript transform plugin (@rollup/plugin-typescript, @rollup/plugin-swc, rollup-plugin-esbuild) that strips `export as namespace` for the bundle target.
  2. Move the directive into a separate `.d.ts` that Rollup ignores rather than bundles.
  3. Remove the line if the global exposure is not needed for the bundle output.

Example fix

// before
export as namespace MyLib;
export function greet() {}

// after
export function greet() {}
Defensive patterns

Strategy: validation

Validate before calling

// Detect `export as namespace`.
function hasTsNamespaceExport(src) {
  return /^\s*export\s+as\s+namespace\s+/m.test(src);
}
if (hasTsNamespaceExport(code)) {
  throw new Error('Source uses `export as namespace`; move to a .d.ts or transpile.');
}

Try / catch

try {
  await rollup({ input });
} catch (err) {
  if (String(err.message).includes('ModuleDecl::TsNamespaceExport')) {
    throw new Error('`export as namespace` reached the native parser; strip it via a TS plugin.');
  }
  throw err;
}

Prevention

When it happens

Trigger: Source contains `export as namespace React` or `export as namespace MyLib`. The ModuleDecl::TsNamespaceExport node reaches convert_module_declaration with no store arm. Common in UMD-style library declarations.

Common situations: Bundling a .ts that declares a UMD/global namespace. Pulling in a library's `.d.ts`-style source that includes the directive. Authoring a library meant to be consumed both as a module and as a global.

Related errors


AI-assisted analysis of rollup/rollup@ddc4ffab62 (2026-08-03). Data as JSON: /data/errors/7b29d0db89c40ba7.json. Report an issue: GitHub.