swc-project/swc · error

unable to access unknown nodes

Error message

unable to access unknown nodes

What it means

When babelify converts `Stmt::Decl`, it maps each declaration kind (class, function, var, using, and the TS declaration forms) to a Babel statement. The `_` arm inside the Decl match is compiled only under the `swc_ast_unknown` cfg and panics on a Decl variant this build of swc_estree_compat does not recognize.

Source

Thrown at crates/swc_estree_compat/src/babelify/stmt.rs:78

            Stmt::Switch(s) => Statement::Switch(s.babelify(ctx)),
            Stmt::Throw(s) => Statement::Throw(s.babelify(ctx)),
            Stmt::Try(s) => Statement::Try(s.babelify(ctx)),
            Stmt::While(s) => Statement::While(s.babelify(ctx)),
            Stmt::DoWhile(s) => Statement::DoWhile(s.babelify(ctx)),
            Stmt::For(s) => Statement::For(s.babelify(ctx)),
            Stmt::ForIn(s) => Statement::ForIn(s.babelify(ctx)),
            Stmt::ForOf(s) => Statement::ForOf(s.babelify(ctx)),
            Stmt::Decl(decl) => match decl {
                Decl::Class(d) => Statement::ClassDecl(d.babelify(ctx)),
                Decl::Fn(d) => Statement::FuncDecl(d.babelify(ctx)),
                Decl::Var(d) => Statement::VarDecl(d.babelify(ctx)),
                Decl::Using(d) => Statement::UsingDecl(d.babelify(ctx)),
                Decl::TsInterface(d) => Statement::TSInterfaceDecl(d.babelify(ctx)),
                Decl::TsTypeAlias(d) => Statement::TSTypeAliasDecl(d.babelify(ctx)),
                Decl::TsEnum(d) => Statement::TSEnumDecl(d.babelify(ctx)),
                Decl::TsModule(d) => Statement::TSModuleDecl(d.babelify(ctx)),
                #[cfg(swc_ast_unknown)]
                _ => panic!("unable to access unknown nodes"),
            },
            Stmt::Expr(s) => Statement::Expr(s.babelify(ctx)),
            #[cfg(swc_ast_unknown)]
            _ => panic!("unable to access unknown nodes"),
        }
    }
}

impl Babelify for ExprStmt {
    type Output = ExpressionStatement;

    fn babelify(self, ctx: &Context) -> Self::Output {
        ExpressionStatement {
            base: ctx.base(self.span),
            expression: Box::alloc().init(self.expr.babelify(ctx).into()),
        }
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Build the estree host without `--cfg=swc_ast_unknown`
  2. Align all swc crates to one swc_core release
  3. Cross boundaries via serialization so unknown variants fail as decode errors
  4. Add the missing Decl mapping in stmt.rs upstream

Example fix

# before
RUSTFLAGS="--cfg=swc_ast_unknown" cargo build

# after
cargo build
Defensive patterns

Strategy: validation

Validate before calling

#[cfg(swc_ast_unknown)]
compile_error!("babelify panics on Unknown Decl nodes; build without --cfg=swc_ast_unknown");

Try / catch

use std::panic::{catch_unwind, AssertUnwindSafe};

catch_unwind(AssertUnwindSafe(|| program.babelify()))
    .map_err(|p| anyhow!("babelify panicked: {:?}", p))?;

Prevention

When it happens

Trigger: Babelify a statement containing an Unknown/newer Decl variant — e.g. a declaration kind added by a newer swc_ecma_ast — while the binary was compiled with `--cfg=swc_ast_unknown`.

Common situations: Plugin builds where the cfg is auto-enabled; dependency drift between swc_ecma_ast and swc_estree_compat; forks adding declaration nodes without babelify arms.

Related errors


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