{"record":{"id":"aeb7d272141c2eb9","repo":"swc-project/swc","slug":"failed-to-parse-jsx-option-is-not-an-expr","errorCode":null,"errorMessage":"failed to parse jsx option {}: '{}' is not an expression","messagePattern":"failed to parse jsx option (.+?): '(.+?)' is not an expression","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_ecma_transforms_optimization/src/const_modules.rs","lineNumber":71,"sourceCode":"    if let Some(expr) = CACHE.get(&fm.src) {\n        return expr.clone();\n    }\n\n    let expr = parse_file_as_expr(\n        &fm,\n        Default::default(),\n        Default::default(),\n        None,\n        &mut Vec::new(),\n    )\n    .map_err(|e| {\n        if HANDLER.is_set() {\n            HANDLER.with(|h| e.into_diagnostic(h).emit())\n        }\n    })\n    .map(drop_span)\n    .unwrap_or_else(|()| {\n        panic!(\n            \"failed to parse jsx option {}: '{}' is not an expression\",\n            name, fm.src,\n        )\n    });\n\n    let expr = Arc::new(*expr);\n\n    CACHE.insert(fm.src.clone(), expr.clone());\n\n    expr\n}\n\nstruct ConstModules {\n    globals: HashMap<Wtf8Atom, HashMap<Wtf8Atom, Arc<Expr>>>,\n    scope: Scope,\n}\n\n#[derive(Default)]","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_ecma_transforms_optimization/src/const_modules.rs#L53-L89","documentation":"For the const-modules transform, every globals value is parsed as a JavaScript expression with parse_file_as_expr (per export name, cached by source text). If parsing fails, a diagnostic is emitted first when a HANDLER is set, then the code panics with 'failed to parse jsx option {name}: \\'{src}\\' is not an expression'. Values must be expressions, not statements.","triggerScenarios":"jsc.transform.constModules.globals entries whose value strings are statements (\"let a = 1\", \"import x\") or contain syntax errors (unbalanced brackets, stray characters); the (name, src) pair is reported in the panic.","commonSituations":"Porting webpack DefinePlugin/babel-plugin-transform-define values that were loose strings, values intended as statements or declarations, template-generated values with trailing semicolons plus statements, JSON configs where quoting got mangled.","solutions":["Make every globals value a valid expression: \"true\", \"'production'\", \"(() => { ... })()\"","Wrap statement-like logic in an IIFE so it becomes a single expression","Check the panic text for the exact (name, src) pair that failed and fix just that entry","Pre-validate values on the JS side by attempting new Function('return (' + value + ')')"],"exampleFix":"// before (.swcrc)\n\"globals\": { \"@app/env\": { \"MODE\": \"const MODE = 'dev'\" } }\n\n// after\n\"globals\": { \"@app/env\": { \"MODE\": \"'dev'\" } }","handlingStrategy":"validation","validationCode":"// JS: sanity-check every globals value parses as an expression\nfunction validateConstModules(globals) {\n  for (const [mod, entries] of Object.entries(globals)) {\n    for (const [name, src] of Object.entries(entries)) {\n      try { new Function(`return (${src})`); }\n      catch { throw new Error(`globals[\"${mod}\"].\"${name}\" is not an expression: ${src}`); }\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Store expressions, not statements, as globals values","Wrap multi-statement logic in IIFEs","Validate the config before builds with the Function-based check above"],"tags":["const-modules","define","config","parse-error","globals"],"backgroundTag":"config-expression-parse-failed","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}