karatelabs/karate · error · JsErrorException (typeError)

cannot create property

Error message

cannot create property '${name}' on ${typeOf(receiver)}

What it means

Mirrors the ECMAScript strict-mode rule for property creation on primitives: a `super` write whose `this` is a primitive (e.g. `B.prototype.m.call(3)`) cannot create a new property, so in strict mode Karate throws this TypeError; in sloppy mode it silently ignores the write. It only fires for property creation on a non-object receiver during a super-property set.

Solutions

  1. Call the method with a proper object receiver: `B.prototype.m.call(obj)` where obj is an object, not a primitive.
  2. Use `new` to create an instance instead of borrowing the method with a primitive this.
  3. Wrap/beforehand-coerce the receiver: `Object(3)` so the receiver is a boxed object.
  4. If the write is intentionally a no-op, run without strict mode (sloppy mode ignores it).

Example fix

// before
* eval B.prototype.m.call(3)
// after
* eval B.prototype.m.call(new B())
Defensive patterns

Strategy: validation

Validate before calling

// ensure receiver is an object before method borrow
if (typeof recv !== 'object' || recv === null) recv = Object(recv);

Type guard

function isObjectReceiver(v) { return v !== null && (typeof v === 'object' || typeof v === 'function'); }

Prevention

When it happens

Trigger: Calling a class/prototype method with `.call(<primitive>)` / `.apply(<primitive>)` where the method performs `super.x = value` (creating a new property on the super target's receiver), while strict mode is enabled in the embedded JS engine.

Common situations: Porting real JavaScript class hierarchies into Karate JS and invoking methods with a primitive this (numbers, strings, booleans) instead of an object instance.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/PropertyAccess.java:1186

            }
            if (receiver != object) {
                if (receiver instanceof ObjectLike receiverObj) {
                    // super data write: no accessor anywhere on the base's
                    // chain, so the property is created/updated on the
                    // instance. putMember on the receiver still honors an own
                    // accessor and writable=false there (the spec's
                    // receiver-side checks).
                    Object oldValue = receiverObj.getMember(name);
                    receiverObj.putMember(name, value, context, context.strict);
                    firePropertySet(context, name, value, oldValue, receiver, trackingNode);
                    return;
                }
                // Non-object receiver (a super write with a primitive `this`,
                // e.g. B.prototype.m.call(3)): the write can neither create a
                // property on the primitive nor be allowed to land on the
                // shared prototype. Strict: TypeError; sloppy: silent no-op.
                if (context.strict) {
                    throw JsErrorException.typeError(
                            "cannot create property '" + name + "' on " + Terms.typeOf(receiver));
                }
                return;
            }
            Object oldValue = objectLike.getMember(name);
            objectLike.putMember(name, value, context, context.strict);
            firePropertySet(context, name, value, oldValue, object, trackingNode);
        } else if (object instanceof Map) {
            Map<String, Object> map = (Map<String, Object>) object;
            Object oldValue = map.get(name);
            map.put(name, value);
            firePropertySet(context, name, value, oldValue, object, trackingNode);
        } else if (context.root.bridge != null) {
            try {
                if (object instanceof ExternalAccess ja) {
                    ja.setProperty(name, value);
                } else {
                    ExternalAccess ja = context.root.bridge.forInstance(object);

View on GitHub (pinned to a22eb90246)