{"record":{"id":"b9e21740db9983e3","repo":"swc-project/swc","slug":"illegal-conversion-cannot-convert-to-exprout","errorCode":null,"errorMessage":"illegal conversion: Cannot convert {:?} to ExprOutput","messagePattern":"illegal conversion: Cannot convert (.+?) to ExprOutput","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_estree_compat/src/babelify/expr.rs","lineNumber":97,"sourceCode":"                    Lit::Str(s) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::String(s.babelify(ctx)))),\n                    ),\n                    Lit::Bool(b) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::Boolean(b.babelify(ctx)))),\n                    ),\n                    Lit::Null(n) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::Null(n.babelify(ctx)))),\n                    ),\n                    Lit::Num(n) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::Numeric(n.babelify(ctx)))),\n                    ),\n                    Lit::BigInt(i) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::BigInt(i.babelify(ctx)))),\n                    ),\n                    Lit::Regex(r) => ExprOutput::Expr(\n                        Box::alloc().init(Expression::Literal(Literal::RegExp(r.babelify(ctx)))),\n                    ),\n                    Lit::JSXText(_) => panic!(\n                        \"illegal conversion: Cannot convert {:?} to ExprOutput\",\n                        &lit\n                    ), // TODO(dwoznicki): is this really illegal?\n                    #[cfg(swc_ast_unknown)]\n                    _ => panic!(\"unable to access unknown nodes\"),\n                }\n            }\n            Expr::Tpl(t) => {\n                ExprOutput::Expr(Box::alloc().init(Expression::TemplateLiteral(t.babelify(ctx))))\n            }\n            Expr::TaggedTpl(t) => {\n                ExprOutput::Expr(Box::alloc().init(Expression::TaggedTemplate(t.babelify(ctx))))\n            }\n            Expr::Arrow(a) => {\n                ExprOutput::Expr(Box::alloc().init(Expression::ArrowFunc(a.babelify(ctx))))\n            }\n            Expr::Class(c) => {\n                ExprOutput::Expr(Box::alloc().init(Expression::Class(c.babelify(ctx))))","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_estree_compat/src/babelify/expr.rs#L79-L115","documentation":"In the generic expression babelify (expr.rs:77-104), a Lit::JSXText literal has no Babel Expression counterpart — Babel only permits JSXText inside JSX text positions — so conversion panics. The SWC parser only ever produces JSXText inside JSX elements, so reaching this arm means a plugin, codemod, or hand-built AST placed JSXText into a plain expression slot; the code even carries a TODO asking whether this is really illegal.","triggerScenarios":"Babelifying an AST in which Expr::Lit(Lit::JSXText(..)) appears in a general expression position — typically a swc plugin that lifted JSX children into expression slots, or a manually constructed fixture.","commonSituations":"Writing swc plugins that rearrange JSX children lists; AST test fixtures constructed by hand; round-tripping JSX through custom transforms.","solutions":["Keep JSXText nodes inside JSXElement children where they belong; fix the plugin that relocated them.","Run the react/jsx transform before babelify so all JSX (including JSXText) is lowered to calls and string literals.","When building AST programmatically, use Lit::Str for text values instead of Lit::JSXText."],"exampleFix":"// before: plugin emits JSXText as a standalone expression\nExpr::Lit(Lit::JSXText(text))\n\n// after: use a string literal outside JSX\nExpr::Lit(Lit::Str(text.into()))","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Detect JSXText literals outside JSX text positions before babelify.\nfn has_jsxtext_in_expr(program: &Program) -> bool {\n    struct Scan(bool);\n    impl Visit for Scan {\n        fn visit_expr(&mut self, e: &Expr) {\n            if matches!(e, Expr::Lit(Lit::JSXText(_))) { self.0 = true; }\n            e.visit_children_with(self);\n        }\n        // JSX element internals are converted by the JSX path; skip them\n        fn visit_jsx_element(&mut self, _: &JSXElement) {}\n    }\n    let mut s = Scan(false);\n    program.visit_with(&mut s);\n    s.0\n}","tryCatchPattern":null,"preventionTips":["Run the react/jsx transform before estree conversion so JSX nodes never reach generic paths.","In plugins, never move JSX children into plain expression slots; use Lit::Str for text.","Round-trip small AST fixtures through babelify in tests to catch misplaced nodes early."],"tags":["swc","estree","babelify","jsx","panic"],"backgroundTag":"ast-conversion-unsupported-node","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-08-22T14:17:55.899Z"}