swc-project/swc · error

illegal conversion: Cannot convert {:?} to PatOutput

Error message

illegal conversion: Cannot convert {:?} to PatOutput

What it means

When swc_ecma_parser runs with error recovery, malformed binding patterns are replaced by `Pat::Invalid` placeholder nodes instead of aborting the parse. ESTree has no representation for an invalid pattern, so babelify panics rather than inventing data. Hitting this panic means the program you are converting still contains parser-recovery artifacts.

Source

Thrown at crates/swc_estree_compat/src/babelify/pat.rs:36

    Array(ArrayPattern),
    Rest(RestElement),
    Object(ObjectPattern),
    Assign(AssignmentPattern),
    Expr(Box<Expression>),
}

impl Babelify for Pat {
    type Output = PatOutput;

    fn babelify(self, ctx: &Context) -> Self::Output {
        match self {
            Pat::Ident(i) => PatOutput::Id(i.babelify(ctx)),
            Pat::Array(a) => PatOutput::Array(a.babelify(ctx)),
            Pat::Rest(r) => PatOutput::Rest(r.babelify(ctx)),
            Pat::Object(o) => PatOutput::Object(o.babelify(ctx)),
            Pat::Assign(a) => PatOutput::Assign(a.babelify(ctx)),
            Pat::Expr(e) => PatOutput::Expr(Box::alloc().init(e.babelify(ctx).into())),
            Pat::Invalid(_) => panic!(
                "illegal conversion: Cannot convert {:?} to PatOutput",
                &self
            ),
            #[cfg(swc_ast_unknown)]
            _ => panic!("unable to access unknown nodes"),
        }
    }
}

impl From<PatOutput> for Pattern {
    fn from(pat: PatOutput) -> Self {
        match pat {
            PatOutput::Assign(a) => Pattern::Assignment(a),
            PatOutput::Array(a) => Pattern::Array(a),
            PatOutput::Object(o) => Pattern::Object(o),
            _ => panic!("illegal conversion: Cannot convert {:?} to Pattern", &pat),
        }
    }

View on GitHub (pinned to 5176682b65)

Solutions

  1. After parsing, abort when `parser.take_errors()` is non-empty before calling babelify
  2. Fix the malformed destructuring/binding syntax in the input source
  3. Re-parse without recovery so invalid input fails at the parse stage with a real diagnostic
  4. Maintainer: return an error or map to an estree Invalid node instead of panicking on Pat::Invalid

Example fix

// before
let module = parser.parse_module().map_err(|e| anyhow!(e))?;
let estree = module.babelify(); // panics if recovery left Pat::Invalid

// after
let module = parser.parse_module().map_err(|e| anyhow!(e))?;
if !parser.take_errors().is_empty() {
    return Err(anyhow!("refusing to babelify recovered AST"));
}
let estree = module.babelify();
Defensive patterns

Strategy: validation

Validate before calling

use swc_ecma_ast::{Module, Pat};
use swc_ecma_visit::{Visit, VisitWith};

#[derive(Default)]
struct InvalidPats(Vec<swc_common::Span>);

impl Visit for InvalidPats {
    fn visit_pat(&mut self, p: &Pat) {
        if let Pat::Invalid(i) = p { self.0.push(i.span); }
        p.visit_children_with(self);
    }
}

fn has_invalid_pats(m: &Module) -> bool {
    let mut v = InvalidPats::default();
    m.visit_with(&mut v);
    !v.0.is_empty()
}

Type guard

fn is_convertible_pat(p: &Pat) -> bool {
    !matches!(p, Pat::Invalid(_))
}

Try / catch

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

let estree = catch_unwind(AssertUnwindSafe(|| program.babelify()))
    .map_err(|_| anyhow!("AST contains invalid/recovered nodes"))?;

Prevention

When it happens

Trigger: Parse source with recovery enabled, ignore the error list, then babelify: inputs like `var {a b} = x;`, `function f([a,,,) {}` or `let [1] = y;` leave Pat::Invalid nodes that reach pat.rs:36 during conversion.

Common situations: Lint/autofix/codemod tools that deliberately parse broken code with a lenient parser config and then convert the recovered AST to estree; pipelines that never call `parser.take_errors()`; hand-built ASTs using `Pat::Invalid` (e.g. via `Take::dummy()`).

Related errors


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