swc-project/swc · error
emitting decorator metadata while using new proposal
Error message
emitting decorator metadata while using new proposal
What it means
SWC's decorators pass can only emit decorator metadata (the design:type information used e.g. by NestJS) in legacy-decorator mode. The standard (2022+) proposal path has no metadata story, so constructing the pass with `legacy: false` together with `emitMetadata: true` panics immediately with unimplemented!.
Solutions
- Set "legacy": true whenever "emitMetadata": true is required (legacy mode supports metadata)
- Keep the new proposal only with "emitMetadata": false (or omitted)
- Remove the decorators config entirely if the project does not use decorators
Example fix
// before (.swcrc)
{ "jsc": { "parser": { "syntax": "typescript", "decorators": true },
"decorators": { "legacy": false, "emitMetadata": true } } }
// after
{ "jsc": { "parser": { "syntax": "typescript", "decorators": true },
"decorators": { "legacy": true, "emitMetadata": true } } } Defensive patterns
Strategy: validation
Validate before calling
// Validate decorator config before constructing the pass / spawning swc
const d = cfg.jsc?.decorators ?? {};
if (d.emitMetadata === true && d.legacy !== true) {
throw new Error('emitMetadata requires decorators.legacy = true');
} Type guard
type DecoratorsConfig =
| { legacy: true; emitMetadata?: boolean }
| { legacy?: false; emitMetadata?: false };
function isValid(cfg: DecoratorsConfig): boolean {
return cfg.legacy === true || cfg.emitMetadata !== true;
} Prevention
- Treat { legacy: false, emitMetadata: true } as an invalid config in your swcrc loader
- Add a config schema check (zod/json-schema) in front of user-provided swc configs
- For NestJS-style DI, standardize on legacy: true + emitMetadata: true
When it happens
Trigger: Configuring jsc.decorators as `{ "legacy": false, "emitMetadata": true }` (or legacy omitted, defaulting to false, with emitMetadata true). The panic happens when the pass is constructed, before any input is read.
Common situations: Enabling emitMetadata for NestJS/typedi dependency injection while also trying out the new decorator proposal; copying a Babel config where both flags coexisted; upgrading configs where legacy previously defaulted true.
Related errors
- ClassMember
- jsc.experimental.emitIsolatedDts is enabled but the syntax…
- Babel doesn't support this right now.
- {decl:?}
- Decl in ExportDecl
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/7d56cad8b02eac5d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/swc_ecma_transforms_proposal/src/decorators/mod.rs:65
/// ```js
/// class C {
/// @enumerable(false)
/// method() { }
/// }
///
/// function enumerable(value) {
/// return function (target, key, descriptor) {
/// descriptor.enumerable = value;
/// return descriptor;
/// }
/// }
/// ```
pub fn decorators(c: Config) -> impl Pass {
if c.legacy {
Either::Left(visit_mut_pass(self::legacy::new(c.emit_metadata)))
} else {
if c.emit_metadata {
unimplemented!("emitting decorator metadata while using new proposal")
}
Either::Right(fold_pass(Decorators {
is_in_strict: false,
vars: Default::default(),
}))
}
}
#[derive(Debug, Default, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
pub legacy: bool,
#[serde(default)]
pub emit_metadata: bool,
pub use_define_for_class_fields: bool,
}
View on GitHub (pinned to 5176682b65)