{"record":{"id":"b48986ae3aef975e","repo":"swc-project/swc","slug":"cannot-convert-p-to-param","errorCode":null,"errorMessage":"Cannot convert {p:?} to Param","messagePattern":"Cannot convert (.+?) to Param","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/babelify/pat.rs","lineNumber":132,"sourceCode":"                &pat\n            ),\n            PatOutput::Assign(_) => panic!(\n                \"illegal conversion: Cannot convert {:?} to AssignmentPatternLeft\",\n                &pat\n            ),\n        }\n    }\n}\n\nimpl From<PatOutput> for Param {\n    fn from(pat: PatOutput) -> Self {\n        match pat {\n            PatOutput::Id(i) => Param::Id(i),\n            PatOutput::Rest(r) => Param::Rest(r),\n            PatOutput::Array(p) => Param::Pat(Pattern::Array(p)),\n            PatOutput::Object(p) => Param::Pat(Pattern::Object(p)),\n            PatOutput::Assign(p) => Param::Pat(Pattern::Assignment(p)),\n            PatOutput::Expr(p) => panic!(\"Cannot convert {p:?} to Param\"),\n        }\n    }\n}\n\nimpl From<PatOutput> for CatchClauseParam {\n    fn from(pat: PatOutput) -> Self {\n        match pat {\n            PatOutput::Id(i) => CatchClauseParam::Id(i),\n            PatOutput::Array(a) => CatchClauseParam::Array(a),\n            PatOutput::Object(o) => CatchClauseParam::Object(o),\n            _ => panic!(\n                \"illegal conversion: Cannot convert {:?} to CatchClauseParam\",\n                &pat\n            ),\n        }\n    }\n}\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/babelify/pat.rs#L114-L150","documentation":"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.","triggerScenarios":"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.","commonSituations":"Tools that parse invalid code with recovery and convert to estree anyway; higher-order-executor codemods injecting computed params; fuzzing-generated ASTs.","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"],"exampleFix":"// before\nlet estree = module.babelify(); // panics on `function f(a.b) {}`\n\n// after\nif !parser.take_errors().is_empty() {\n    return Err(anyhow!(\"recovered AST has invalid parameters\"));\n}\nlet estree = module.babelify();","handlingStrategy":"validation","validationCode":"use swc_ecma_ast::Pat;\n\nfn params_ok(params: &[Pat]) -> bool {\n    params.iter().all(|p| {\n        matches!(p, Pat::Ident(_) | Pat::Array(_) | Pat::Rest(_) | Pat::Object(_) | Pat::Assign(_))\n    })\n}","typeGuard":"fn is_valid_param(p: &Pat) -> bool {\n    !matches!(p, Pat::Expr(_) | Pat::Invalid(_))\n}","tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\n\ncatch_unwind(AssertUnwindSafe(|| program.babelify()))\n    .map_err(|_| anyhow!(\"expression in parameter position\"))?;","preventionTips":["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"],"tags":["rust","swc","babelify","function-parameters","parser-error-recovery","panic"],"backgroundTag":"unsupported-ast-conversion","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}