karatelabs/karate · error · JsErrorException (typeError)
' ' was defined without a setter
Error message
'${pn.name}' was defined without a setter What it means
When writing a private accessor via `PrivateAccess.set`, the engine found the private name declared as an accessor with only a getter (no setter). Assigning to a getter-only private accessor is a TypeError per the ES spec.
Solutions
- Add a setter to the accessor declaration.
- Remove or redirect the assignment if the member is intentionally read-only.
- Convert the member to a plain private field `#prop` if direct writes are acceptable.
- Write to an underlying private field that the getter reads instead.
Example fix
// before
class C { get #x() { return 1; } }
new C().#x = 2; // TypeError: '#x' was defined without a setter
// after
class C { #x = 1; } // or add: set #x(v) { ... } Defensive patterns
Strategy: validation
Validate before calling
// verify a setter exists before assigning to a private accessor const hasSetter = /set\s+#prop\b|accessor\s+#prop\b/.test(classSource);
Type guard
function privateAccessorWritable(classSrc, name) { return new RegExp('(set\\s+#' + name + '|accessor\\s+#' + name + ')').test(classSrc); } Try / catch
try { obj.#prop = v; } catch (e) { if (e instanceof TypeError && e.message.includes('without a setter')) { /* write underlying field instead */ } else { throw e; } } Prevention
- Declare setter alongside getter for accessors that will be written.
- Grep for assignments to `#name` before deleting a setter.
- Use plain private fields when writes are expected.
When it happens
Trigger: Assigning `obj.#prop = value` where the class declared `accessor #prop` (or an accessor pair) without a `set` accessor.
Common situations: Read-only private accessors assigned from subclass or internal code; a refactor that dropped the setter while write sites remained; confusing plain private fields (which accept writes) with accessors (which do not).
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- ' ' was defined without a getter
- Cannot write to private method
- Cannot private member from an object whose class did not…
- toBytes() argument must be a list of numbers, got
- toBytes() list must contain only numbers, got
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/5b2a3d69be7e2494.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java:71
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)