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
- Validate parameter lists before babelify: every param must be Ident/Array/Rest/Object/Assign, never Pat::Expr
- Fix or reject the source with the invalid parameter
- In transforms, build params only from valid binding shapes
- 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
- Check `parser.take_errors()` before babelify — expression params only arise from recovery
- In transforms, build function/arrow params only from binding shapes
- Fuzz-test AST builders to ensure they never emit Pat::Expr params
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
- illegal conversion: Cannot convert {:?} to PatOutput
- illegal conversion: Cannot convert {:?} to LVal
- illegal conversion: Cannot convert {:?} to AssignmentPattern
- illegal conversion: Cannot convert {:?} to ObjectMember
- unable to access unknown nodes
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/b48986ae3aef975e.
Report an issue: GitHub.