karatelabs/karate · error · JsErrorException (typeError)
Cannot write to private method
Error message
Cannot write to private method ${pn.name} What it means
`PrivateAccess.set` throws this TypeError when code assigns to a private method (`obj.#method = ...`). Private methods are immutable class members; the ES spec forbids writing to them, so the engine rejects the assignment instead of silently overwriting.
Solutions
- Remove the assignment to the private method.
- Change the declaration from a private method to a private field if rebinding is intended (`#run = () => {...}`).
- Use a different private field to hold the replacement function instead of reassigning the method name.
Example fix
// before
class C { #run() {} init() { this.#run = () => {}; } } // TypeError
// after
class C { #run = () => {}; } Defensive patterns
Strategy: validation
Validate before calling
// ensure the target is a private field, not a method, before assigning
const isMethod = /#run\s*\(/.test(classSource);
if (isMethod) throw new Error('cannot assign to private method #run'); Type guard
function isPrivateMethod(classSrc, name) { return new RegExp('#' + name + '\\s*\\(').test(classSrc); } Try / catch
try { c.#run = fn; } catch (e) { if (e instanceof TypeError && /Cannot write to private method/.test(e.message)) { c = new CWithField(fn); } else { throw e; } } Prevention
- Never assign to `#method` names; use a separate private field for swappable behavior.
- Declare configurable behavior as private fields initialized with functions.
- Review refactors that convert fields to methods for lingering assignments.
When it happens
Trigger: An assignment expression whose LHS resolves to a private name of kind METHOD, e.g. `this.#run = fn` inside or against a class that declared `#run() {}` as a method.
Common situations: Attempting to monkey-patch a private method from within the class; typos where a field was intended (`#handler = ...`) but was declared as a method; refactors that converted fields to methods while old assignment code remained.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot assign to read only property 'length' of object…
- ' ' was defined without a getter
- ' ' was defined without a setter
- Cannot private member from an object whose class did not…
- toBytes() argument must be a list of numbers, got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/96aafad4df2090c0.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java:68
static Object get(Object target, PrivateName pn, CoreContext context) {
JsObject obj = branded(target, pn, "read");
return switch (pn.kind) {
case FIELD -> obj.getPrivate(pn);
case METHOD -> pn.method;
case ACCESSOR -> {
if (pn.getter == null) {
throw JsErrorException.typeError("'" + pn.name + "' was defined without a getter");
}
yield Interpreter.invokeGetter(pn.getter, target, context);
}
};
}
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)