swc-project/swc · error · Error

Decorating class property failed. Please ensure that proposa

Error message

Decorating class property failed. Please ensure that proposal-class-properties is enabled and set to use loose mode. To use proposal-class-properties in spec mode with decorators, wait for the next major version of decorators in stage 2.

What it means

SWC injects this helper when legacy (stage-1) decorators are compiled together with class properties in spec mode, a combination the legacy decorator runtime cannot support. Instead of implementing it, the compiled code calls `_initializer_warning_helper`, which unconditionally throws this Error the moment the decorated field initializer would run. The message is really a build-configuration diagnostic surfaced at runtime: it instructs you to compile class fields in loose mode.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_initializer_warning_helper.rs:11

// This file is generated by `cargo codegen helpers`. DO NOT MODIFY.

use super::{HelperDef, HelperName};

pub const DEF: HelperDef = HelperDef {
    name: HelperName::initializer_warning_helper,
    local: "_initializer_warning_helper",
    import_path: "@swc/helpers/_/_initializer_warning_helper",
    #[cfg(feature = "inline-helpers")]
    source: r#"function _initializer_warning_helper(descriptor, context) {
    throw new Error(
        "Decorating class property failed. Please ensure that "
            + "proposal-class-properties is enabled and set to use loose mode. "
            + "To use proposal-class-properties in spec mode with decorators, wait for "
            + "the next major version of decorators in stage 2."
    );
}
"#,
    #[cfg(feature = "inline-helpers")]
    deps: super::HelperBitmap::from_bits(0x00000000000000000100000000000000),
};

#[cfg(feature = "inline-helpers")]
pub fn stmts() -> &'static [swc_ecma_ast::Stmt] {
    static STMTS: once_cell::sync::Lazy<Vec<swc_ecma_ast::Stmt>> =
        once_cell::sync::Lazy::new(|| super::super::parse(DEF.source, DEF.import_path));
    &STMTS
}

View on GitHub (pinned to 5176682b65)

Solutions

  1. In .swcrc, pair legacy decorators with loose class fields: set `jsc.transform.legacyDecorator: true` together with `jsc.assumptions.setPublicClassFields: true` (or compile with `env.mode: "loose"`).
  2. If legacy decorators are not required, switch to standard decorators (`jsc.transform.decoratorVersion: "2022-03"` or later) and update decorator-using libraries to versions that support them.
  3. Upgrade the decorator library (TypeORM 0.3+, class-transformer with modern experimentalDecorators alternatives, MobX 10+) so legacy mode is no longer needed.
  4. As a last resort, remove decorators from field initializers and apply their logic in the constructor.

Example fix

// before (.swcrc)
{
  "jsc": {
    "transform": { "legacyDecorator": true }
  }
}
// throws at runtime: Decorating class property failed...

// after (.swcrc)
{
  "jsc": {
    "transform": { "legacyDecorator": true },
    "assumptions": { "setPublicClassFields": true }
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-build config check (Node): fail CI if legacy decorators are enabled without loose class fields.
const cfg = require('./.swcrc');
const jsc = (Array.isArray(cfg) ? cfg[0] : cfg).jsc;
const legacy = jsc?.transform?.legacyDecorator || jsc?.experimental?.decorators === true;
const looseFields = jsc?.assumptions?.setPublicClassFields === true || jsc?.transform?.reactImplicitReturn ?? false;
if (legacy && !jsc?.assumptions?.setPublicClassFields) {
  throw new Error('legacyDecorator requires jsc.assumptions.setPublicClassFields: true');
}

Prevention

When it happens

Trigger: Source like `class C { @dec x = 1; }` compiled with legacy decorators enabled (`.swcrc` `jsc.transform.legacyDecorator: true` or equivalent) while class fields are transformed in spec mode (`jsc.assumptions.setPublicClassFields` not set, env not in loose mode). The error fires as soon as the decorated class is defined or instantiated in the emitted output.

Common situations: Next.js or raw .swcrc configs enabling legacy decorators for TypeORM/class-validator/older MobX while leaving SWC's default spec-mode class fields; migrating from Babel where `@babel/plugin-proposal-decorators {legacy: true}` was paired with `@babel/plugin-proposal-class-properties {loose: true}` and the loose half of the pair was lost in translation.

Related errors


AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17). Data as JSON: /api/errors/74853a9708cc36fe. Report an issue: GitHub.