swc-project/swc · error
illegal conversion: Cannot convert {:?} to CatchClauseParam
Error message
illegal conversion: Cannot convert {:?} to CatchClauseParam What it means
Per the grammar a catch parameter is at most an identifier or a binding (destructuring) pattern; rest elements, defaults and expression params are illegal, so `From<PatOutput> for CatchClauseParam` maps only Id/Array/Object and panics on everything else. The catch clause's param is converted at stmt.rs:315 via `self.param.map(|p| p.babelify(ctx).into())`.
Source
Thrown at crates/swc_estree_compat/src/babelify/pat.rs:143
fn from(pat: PatOutput) -> Self {
match pat {
PatOutput::Id(i) => Param::Id(i),
PatOutput::Rest(r) => Param::Rest(r),
PatOutput::Array(p) => Param::Pat(Pattern::Array(p)),
PatOutput::Object(p) => Param::Pat(Pattern::Object(p)),
PatOutput::Assign(p) => Param::Pat(Pattern::Assignment(p)),
PatOutput::Expr(p) => panic!("Cannot convert {p:?} to Param"),
}
}
}
impl From<PatOutput> for CatchClauseParam {
fn from(pat: PatOutput) -> Self {
match pat {
PatOutput::Id(i) => CatchClauseParam::Id(i),
PatOutput::Array(a) => CatchClauseParam::Array(a),
PatOutput::Object(o) => CatchClauseParam::Object(o),
_ => panic!(
"illegal conversion: Cannot convert {:?} to CatchClauseParam",
&pat
),
}
}
}
impl Babelify for ArrayPat {
type Output = ArrayPattern;
fn babelify(self, ctx: &Context) -> Self::Output {
ArrayPattern {
base: ctx.base(self.span),
elements: self
.elems
.into_iter()
.map(|opt| opt.map(|e| e.babelify(ctx).into()))
.collect(),View on GitHub (pinned to 5176682b65)
Solutions
- Validate catch params before babelify: allow only Ident/Array/Object patterns
- Fix the source's catch clause syntax
- In transforms, never emit Rest/Assign/Expr as a catch param
- Abort when parse errors were recovered instead of converting
Example fix
// before
let estree = module.babelify(); // panics on `catch (...r) {}`
// after
fn catch_param_ok(p: &Option<Pat>) -> bool {
p.as_ref().is_none_or(|p| matches!(p, Pat::Ident(_) | Pat::Array(_) | Pat::Object(_)))
}
assert!(catch_param_ok(&catch_clause.param));
let estree = module.babelify(); Defensive patterns
Strategy: validation
Validate before calling
use swc_ecma_ast::Pat;
fn catch_param_ok(p: &Option<Pat>) -> bool {
p.as_ref().is_none_or(|p| matches!(p, Pat::Ident(_) | Pat::Array(_) | Pat::Object(_)))
} Type guard
fn catch_param_convertible(p: &Pat) -> bool {
matches!(p, Pat::Ident(_) | Pat::Array(_) | Pat::Object(_))
} Try / catch
use std::panic::{catch_unwind, AssertUnwindSafe};
catch_unwind(AssertUnwindSafe(|| program.babelify()))
.map_err(|_| anyhow!("illegal catch clause parameter"))?; Prevention
- Validate catch params (Id/Array/Object only) before estree conversion
- Do not generate Rest/Assign/Expr catch params in codemods
- Abort on recovered parse errors — invalid catch clauses come from recovery
When it happens
Trigger: Recovered or hand-built `catch (...r) {}`, `catch ({a} = {}) {}`, or `catch (a.b) {}` — any catch param whose PatOutput is Rest, Assign, or Expr hits the `_` arm.
Common situations: Lenient parses of mistyped catch clauses; codemods rewriting catch params; ASTs assembled programmatically without grammar validation.
Related errors
- unable to access unknown nodes
- illegal conversion: Cannot convert {:?} to PatOutput
- illegal conversion: Cannot convert {:?} to Pattern
- illegal conversion: Cannot convert {:?} to LVal
- illegal conversion: Cannot convert {:?} to AssignmentPattern
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/3a8d52c647b10189.
Report an issue: GitHub.