swc-project/swc · error

Cannot convert {p:?} to Param

Error message

Cannot convert {p:?} to Param

What it means

Babel function parameters (Param) can be an identifier, a rest element, or a destructuring pattern — never an arbitrary expression. `From<PatOutput> for Param` therefore panics on `PatOutput::Expr` instead of guessing a shape. The AST being converted has an expression in parameter position, which only occurs after error recovery or from transforms.

Source

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

                &pat
            ),
            PatOutput::Assign(_) => panic!(
                "illegal conversion: Cannot convert {:?} to AssignmentPatternLeft",
                &pat
            ),
        }
    }
}

impl From<PatOutput> for Param {
    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
            ),
        }
    }
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. Validate parameter lists before babelify: every param must be Ident/Array/Rest/Object/Assign, never Pat::Expr
  2. Fix or reject the source with the invalid parameter
  3. In transforms, build params only from valid binding shapes
  4. Check `parser.take_errors()` after parsing and abort on non-empty

Example fix

// before
let estree = module.babelify(); // panics on `function f(a.b) {}`

// after
if !parser.take_errors().is_empty() {
    return Err(anyhow!("recovered AST has invalid parameters"));
}
let estree = module.babelify();
Defensive patterns

Strategy: validation

Validate before calling

use swc_ecma_ast::Pat;

fn params_ok(params: &[Pat]) -> bool {
    params.iter().all(|p| {
        matches!(p, Pat::Ident(_) | Pat::Array(_) | Pat::Rest(_) | Pat::Object(_) | Pat::Assign(_))
    })
}

Type guard

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

Try / catch

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

catch_unwind(AssertUnwindSafe(|| program.babelify()))
    .map_err(|_| anyhow!("expression in parameter position"))?;

Prevention

When it happens

Trigger: Recovered code like `function f(a.b) {}` or `((a + b) => {});` where the parser kept the invalid parameter as `Pat::Expr`, then the param list is converted via `param.babelify(ctx).into()` into Param.

Common situations: Tools that parse invalid code with recovery and convert to estree anyway; higher-order-executor codemods injecting computed params; fuzzing-generated ASTs.

Related errors


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