swc-project/swc · error · Error

failed to set property

Error message

failed to set property

What it means

The `_set` helper implements `super.prop = value` for targets without native classes. It walks the prototype chain looking for a setter (or a writable data property via `Object.defineProperty` semantics); if no receiver accepts the assignment and the code is strict (ESM always is), it throws `Error("failed to set property")`.

Source

Thrown at crates/swc_ecma_transforms_base/src/helpers/generated/_set.rs:44

            desc = Object.getOwnPropertyDescriptor(receiver, property);
            if (desc) {
                if (!desc.writable) return false;
                desc.value = value;
                Object.defineProperty(receiver, property, desc);
            } else {
                _define_property(receiver, property, value);
            }

            return true;
        };
    }

    return set(target, property, value, receiver);
}

function _set(target, property, value, receiver, isStrict) {
    var s = set(target, property, value, receiver || target);
    if (!s && isStrict) throw new Error("failed to set property");

    return value;
}
"#,
    #[cfg(feature = "inline-helpers")]
    deps: super::HelperBitmap::from_bits(0x00000000000210000008400000000000),
};

#[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. Define a setter for the property on the parent class (or override the accessor in the subclass) so the chain contains an accepting setter.
  2. Store the value on the instance with a different own-property name instead of assigning through `super`.
  3. Replace the assignment with an explicit method call on the parent (`this.setParentValue(v)`).
  4. Before assigning, walk the prototype chain and verify a setter exists (see validation below).

Example fix

// before
class Base { get mode() { return 'read-only'; } }
class Child extends Base {
  set mode(v) { super.mode = v; } // Error: failed to set property
}

// after
class Base {
  #mode = 'default';
  get mode() { return this.#mode; }
  set mode(v) { this.#mode = v; }
}
class Child extends Base {
  set mode(v) { super.mode = v; } // parent now accepts the set
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify a setter exists somewhere on the prototype chain before `super.x = v`.
function chainHasSetter(obj, prop) {
  for (let o = obj; o != null; o = Object.getPrototypeOf(o)) {
    const d = Object.getOwnPropertyDescriptor(o, prop);
    if (d) return d.writable === true || typeof d.set === 'function';
  }
  return false; // plain property addition will apply to the receiver
}
if (!chainHasSetter(Object.getPrototypeOf(this), 'mode')) {
  throw new Error('parent does not accept super.mode assignment');
}
super.mode = value;

Try / catch

try {
  super.prop = value;
} catch (err) {
  if (err instanceof Error && err.message === 'failed to set property') {
    // no accepting setter on the chain — store on the instance instead
    Object.defineProperty(this, 'prop', { value, writable: true, configurable: true });
  } else throw err;
}

Prevention

When it happens

Trigger: Compiled `super.x = v` where every superclass in the chain declares `x` as a getter-only accessor, a non-writable/non-configurable data property, or a Proxy whose `set` trap returns `false` — in strict-mode output.

Common situations: Extending framework base classes that expose read-only computed properties (custom elements, ORM entities) and trying to assign through `super.`; migrating sloppy-mode scripts to ESM where the failed assignment used to be silent; overriding a property that the parent deliberately froze.

Related errors


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