karatelabs/karate · error · JsErrorException

Cannot add property , object is not extensible

Error message

Cannot add property {name}, object is not extensible

What it means

failNotExtensible is the strict-mode rejection helper for adding a string-keyed property to an object that is not extensible (frozen, sealed, or preventExtensions'd). Spec [[Set]] requires a TypeError in strict code; sloppy mode silently ignores the write.

Solutions

  1. Remove the freeze/seal/preventExtensions call if the object must grow
  2. Pre-declare all needed properties before freezing
  3. Use a Map or a fresh mutable object instead of the frozen one

Example fix

// before
var o = Object.preventExtensions({a: 1});
o.b = 2; // TypeError
// after
var o = {a: 1, b: undefined};
o.b = 2;
Defensive patterns

Strategy: validation

Validate before calling

if (!Object.isExtensible(o)) throw new TypeError('cannot add property to non-extensible object');

Type guard

function canAddProp(o) { return Object.isExtensible(o); }

Try / catch

try { o[name] = v; } catch (e) { if (String(e).includes('not extensible')) { o = {...o, [name]: v}; } else { throw e; } }

Prevention

When it happens

Trigger: Strict-mode obj.newProp = value where obj was passed to Object.freeze, Object.seal, or Object.preventExtensions and newProp does not already exist on it.

Common situations: Freezing test fixtures or config then augmenting them; preventExtensions on objects used as ad-hoc maps; code migrating from sloppy to strict (module) code where silent failures become TypeErrors.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/d525679e94d684c0. Report an issue: GitHub.

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/JsObject.java:483

        if (s != null && s.tombstoned) {
            props.remove(name);
        }
    }

    /** True iff {@code name} has a non-tombstoned own slot (excludes intrinsics). */
    boolean ownContainsKey(String name) {
        PropertySlot s = props == null ? null : props.get(name);
        return s != null && !s.tombstoned;
    }

    /** Strict-mode [[Set]] rejection: assigning a non-writable / frozen prop. */
    static void failReadOnly(String name) {
        throw JsErrorException.typeError("Cannot assign to read only property '" + name + "'");
    }

    /** Strict-mode [[Set]] rejection: adding a key to a non-extensible object. */
    static void failNotExtensible(String name) {
        throw JsErrorException.typeError("Cannot add property " + name + ", object is not extensible");
    }

    /** Strict-mode [[Delete]] rejection: removing a non-configurable property. */
    static void failNotConfigurable(String name) {
        throw JsErrorException.typeError("Cannot delete property '" + name + "' of " + "[object Object]");
    }

    @Override
    public void putMember(String name, Object value) {
        putMember(name, value, null, false);
    }

    @Override
    public void putMember(String name, Object value, CoreContext ctx, boolean strict) {
        if ("__proto__".equals(name)) {
            if (value instanceof ObjectLike proto) {
                this.__proto__ = proto;
            } else if (value == null) {

View on GitHub (pinned to a22eb90246)