karatelabs/karate · error · JsErrorException (typeError)

Cannot private member from an object whose class did not…

Error message

Cannot ${verb} private member ${pn.name} from an object whose class did not declare it

What it means

`PrivateAccess.branded` implements the spec's brand check: before reading or writing a private member, the target object must actually have that private member installed by its class. Objects of other classes (or non-objects) fail the check and get this TypeError, keeping `#` members truly private across classes.

Solutions

  1. Invoke the method on a genuine instance of the declaring class instead of via call/apply/bind.
  2. Ensure the object passed in was constructed by the class that declares the private member.
  3. If duck-typing is intended, use public properties or symbols instead of `#private` ones.
  4. Add an `instanceof` check before invoking the private-member-using method.

Example fix

// before
const m = a.getInstance; // borrowed method using this.#state
m.call(b); // TypeError: Cannot read private member #state from an object whose class did not declare it
// after
a.getInstance(); // invoke on the declaring instance, or guard: if (x instanceof C) x.getInstance()
Defensive patterns

Strategy: type-guard

Validate before calling

// verify the receiver is an instance of the declaring class before invoking
if (!(target instanceof C)) throw new Error('method requires a C instance');

Type guard

function isBranded(x, C) { return x instanceof C; }

Try / catch

try { return obj.method(); } catch (e) { if (e instanceof TypeError && /did not declare it/.test(e.message)) { return foreignImpl(obj); } throw e; }

Prevention

When it happens

Trigger: Calling a method that reads `this.#x` with `this` bound to a foreign object (e.g. `OtherClass.prototype.method.call(notAnInstance)`, `Function.prototype.call/apply/bind` misuse, or destructuring a method off its instance).

Common situations: Borrowing methods between similar classes; passing plain objects where class instances are expected; mocking frameworks replacing `this`; using `.call()` to run a class method against a mock.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java:82

    static void set(Object target, PrivateName pn, Object value, CoreContext context) {
        JsObject obj = branded(target, pn, "write");
        switch (pn.kind) {
            case FIELD -> obj.putPrivate(pn, value);
            case METHOD -> throw JsErrorException.typeError("Cannot write to private method " + pn.name);
            case ACCESSOR -> {
                if (pn.setter == null) {
                    throw JsErrorException.typeError("'" + pn.name + "' was defined without a setter");
                }
                Interpreter.invokeSetter(pn.setter, target, value, context);
            }
        }
    }

    private static JsObject branded(Object target, PrivateName pn, String verb) {
        if (target instanceof JsObject obj && obj.hasPrivate(pn)) {
            return obj;
        }
        throw JsErrorException.typeError("Cannot " + verb + " private member " + pn.name
                + " from an object whose class did not declare it");
    }

}

View on GitHub (pinned to a22eb90246)