swc-project/swc · error

internal error: entered unreachable code

Error message

internal error: entered unreachable code

What it means

When swc_bundler finalizes a bundle whose output format is IIFE, may_wrap_with_iife rewrites `export <decl>` statements into properties on the returned object. It converts Class, Fn and Var declarations; any other Decl — TsEnum, TsInterface, TsTypeAlias, TsModule, i.e. TypeScript-only syntax that should have been stripped — hits unreachable!().

Source

Thrown at crates/swc_bundler/src/bundler/finalize.rs:196

                        ModuleDecl::ExportDecl(export) => {
                            match &export.decl {
                                Decl::Class(ClassDecl { ident, .. })
                                | Decl::Fn(FnDecl { ident, .. }) => {
                                    props.push(PropOrSpread::Prop(Box::new(Prop::Shorthand(
                                        ident.clone(),
                                    ))));
                                }
                                Decl::Var(decl) => {
                                    let ids: Vec<Ident> = find_pat_ids(decl);
                                    props.extend(
                                        ids.into_iter()
                                            .map(Prop::Shorthand)
                                            .map(Box::new)
                                            .map(PropOrSpread::Prop),
                                    );
                                }
                                _ => unreachable!(),
                            }

                            Some(export.decl.into())
                        }

                        ModuleDecl::ExportNamed(NamedExport {
                            specifiers,
                            src: None,
                            ..
                        }) => {
                            for s in specifiers {
                                match s {
                                    ExportSpecifier::Namespace(..) => {
                                        // unreachable
                                    }
                                    ExportSpecifier::Default(s) => {
                                        props.push(PropOrSpread::Prop(Box::new(Prop::KeyValue(
                                            KeyValueProp {

View on GitHub (pinned to 5176682b65)

Solutions

  1. Run the TypeScript strip/compile pass before the bundler so only plain ESM reaches finalize
  2. Verify pass ordering in your pipeline: typescript::strip must precede bundling
  3. If TypeScript was already stripped, capture the failing module and report it to swc as a bundler gap

Example fix

// before (raw TS fed to bundler)
export enum Flag { A, B }

// after (pre-stripped by typescript::strip before bundling)
export var Flag;
(function (Flag) {
  Flag[Flag["A"] = 0] = "A";
  Flag[Flag["B"] = 1] = "B";
})(Flag || (Flag = {}));
Defensive patterns

Strategy: validation

Validate before calling

// Detect TS-only exported declarations before bundling with IIFE output
let ts_export = regex::Regex::new(
    r#"(?m)^\s*export\s+(?:enum|interface|type|namespace|module|declare)\b"#,
).unwrap();
for (path, src) in &sources {
    if ts_export.is_match(src) {
        return Err(format!("{} still contains TypeScript exports; strip first", path));
    }
}

Try / catch

match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| bundler.bundle(&entries))) {
    Ok(v) => v?,
    Err(p) => {
        if panic_message(&p).contains("entered unreachable code") && cfg_module_iife {
            // retry after inserting typescript::strip at the front of the pipeline
        } else { std::panic::resume_unwind(p); }
    }
}

Prevention

When it happens

Trigger: Bundling with ModuleType::Iife where an entry still contains TypeScript exports such as `export enum E {}`, `export interface I {}`, `export type T = ...`, or `export namespace N {}` because the TypeScript strip pass never ran (or ran after the bundler).

Common situations: Custom swc pipelines invoking the bundler on raw TypeScript; a pass chain where typescript::strip was accidentally omitted or ordered after bundling; plugins re-inserting TS nodes into the graph.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/ca0825bd0076a43f. Report an issue: GitHub.