swc-project/swc · error
swc does not support record expressions
Error message
swc does not support record expressions
What it means
Swcify in swc_estree_compat maps each swc_estree_ast node to an swc_ecma_ast node. RecordExpression (the `{| a: 1 |}` literal from the Records & Tuples proposal) has no counterpart in SWC's AST, so its impl returns the uninhabited Never type and panics. This is an intentional hard failure marking the syntax as unrepresentable.
Source
Thrown at crates/swc_estree_compat/src/swcify/expr.rs:1130
fn swcify(self, _: &Context) -> Self::Output {
panic!("swc does not support do expressions")
}
}
impl Swcify for PipelinePrimaryTopicReference {
type Output = Never;
fn swcify(self, _: &Context) -> Self::Output {
panic!("swc does not support `PipelinePrimaryTopicReference`")
}
}
impl Swcify for RecordExpression {
type Output = Never;
fn swcify(self, _: &Context) -> Self::Output {
panic!("swc does not support record expressions")
}
}
impl Swcify for TupleExpression {
type Output = Never;
fn swcify(self, _: &Context) -> Self::Output {
panic!("swc does not support tuple expressions")
}
}
impl Swcify for ModuleExpression {
type Output = Never;
fn swcify(self, _: &Context) -> Self::Output {
panic!("swc does not support module expressions")
}
}View on GitHub (pinned to 5176682b65)
Solutions
- Remove @babel/plugin-syntax-record-and-tuple (or the parser flag) so `{| |}` record literals are never produced
- Lower records to plain object expressions (or esbuild/babel output) before feeding the AST to swcify
- Parse the source with swc_ecma_parser, which rejects or handles syntax according to its own feature set
- Pre-validate the ESTree JSON for `type: "RecordExpression"` nodes and fail with a clear diagnostic instead of panicking
Example fix
// before
const rec = {| a: 1 |}; // parsed by babel w/ record-and-tuple syntax
ast.swcify(&ctx); // panics: swc does not support record expressions
// after
const rec = { a: 1 }; // plain object literal
ast.swcify(&ctx); // ok Defensive patterns
Strategy: type-guard
Validate before calling
let mut bad = Vec::new();
find_unsupported(&estree_json, &mut bad); // same walk as error 200
if bad.iter().any(|t| t == "RecordExpression") {
return Err("record literals ({| ... |}) are not supported by swcify".into());
} Type guard
fn is_unsupported_estree_type(t: &str) -> bool {
matches!(
t,
"RecordExpression" | "TupleExpression" | "PipelinePrimaryTopicReference"
| "BindExpression" | "DoExpression" | "ModuleExpression"
)
} Try / catch
let out = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
estree_expr.swcify(&ctx)
}));
if out.is_err() {
// map to a diagnostic naming the unsupported node instead of aborting
return Err("swcify cannot convert this ESTree tree (unsupported proposal syntax)".into());
} Prevention
- Do not enable record-and-tuple syntax plugins in parsers feeding swc_estree_compat
- Convert records to object literals before the AST reaches swcify
- Validate incoming ESTree JSON against a blocklist of unsupported node types
- Prefer swc_ecma_parser for parsing source directly
When it happens
Trigger: Calling `.swcify(ctx)` on an ESTree tree containing a RecordExpression node, i.e. code parsed with @babel/plugin-syntax-record-and-tuple (or an equivalent parser plugin) producing `{| key: value |}` literals that are then converted to SWC.
Common situations: Babel-first pipelines that keep proposal syntax and hand the AST to SWC via swc_estree_compat; mixing parser feature flags (record-and-tuple enabled upstream) with SWC conversion; exploratory tooling that accepts arbitrary ESTree JSON.
Related errors
- swc does not support tuple expressions
- swc does not support `PipelinePrimaryTopicReference`
- swc does not support module expressions
- failed to parse the value of BigIntLiteral
- failed to parse the value of DecimalLiteral
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/3f3bf78ad197e0cb.
Report an issue: GitHub.