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

  1. Validate catch params before babelify: allow only Ident/Array/Object patterns
  2. Fix the source's catch clause syntax
  3. In transforms, never emit Rest/Assign/Expr as a catch param
  4. 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

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


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