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

  1. Set "legacy": true whenever "emitMetadata": true is required (legacy mode supports metadata)
  2. Keep the new proposal only with "emitMetadata": false (or omitted)
  3. 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

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


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)