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
- 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"`).
- 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.
- Upgrade the decorator library (TypeORM 0.3+, class-transformer with modern experimentalDecorators alternatives, MobX 10+) so legacy mode is no longer needed.
- 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
- Whenever you enable `legacyDecorator` in .swcrc, add `setPublicClassFields: true` in the same commit and review it together.
- Add a smoke test that imports and instantiates every decorated class so a bad decorator/class-fields combination fails in CI, not production.
- Pin your swc_core/@swc/core versions and re-run snapshot fixtures after upgrades — decorator handling changed across SWC releases.
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
- unable to access unknown nodes
- multiple constructor?
- emitting decorator metadata while using new proposal
- ClassMember::{:?}
- The requested module '{specifier}' does not provide an expor
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/74853a9708cc36fe.
Report an issue: GitHub.