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
- After parsing, abort when `parser.take_errors()` is non-empty before calling babelify
- Fix the malformed destructuring/binding syntax in the input source
- Re-parse without recovery so invalid input fails at the parse stage with a real diagnostic
- 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
- Always check `parser.take_errors()` after parsing and abort before estree conversion when non-empty
- Do not use Pat::Invalid / Take::dummy() as placeholder in ASTs destined for babelify
- Add fixture tests containing broken destructuring to verify your pipeline rejects them
- Prefer failing the whole conversion over partial output from recovered ASTs
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
- illegal conversion: Cannot convert {:?} to AssignmentPattern
- illegal conversion: Cannot convert {:?} to Pattern
- illegal conversion: Cannot convert {:?} to LVal
- Cannot convert {p:?} to Param
- illegal conversion: Cannot convert {:?} to ObjectMember
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/a489091f2c6f87ee.
Report an issue: GitHub.