karatelabs/karate · error · JsErrorException
Setter must be a function
Error message
Setter must be a function
What it means
Symmetric to the getter check: a 'set' field present (and not undefined) in a property descriptor must be a callable function. Passing null, a value, or any non-callable throws this TypeError per ToPropertyDescriptor.
Solutions
- Pass a real function to set: (obj, 'k', { set(v) { this._k = v; } })
- Omit the set field for read-only accessor or data descriptors
- Use undefined (not null) if you need the key present but inert
- Guard with typeof desc.set === 'function' before defining
Example fix
// before
Object.defineProperty(o, 'x', { set: 42 });
// after
Object.defineProperty(o, 'x', { set(v) { this._x = v; } }); Defensive patterns
Strategy: type-guard
Validate before calling
if (desc.set !== undefined && typeof desc.set !== 'function') throw new TypeError('set must be a function or undefined'); Type guard
function hasValidSetter(desc) { return !('set' in desc) || desc.set === undefined || typeof desc.set === 'function'; } Try / catch
try { Object.defineProperty(o, k, desc); } catch (e) { if (String(e.message).includes('Setter must be a function')) console.error('descriptor.set =', desc.set); else throw e; } Prevention
- Validate accessor pairs together: both get and set must be functions or undefined
- Avoid storing setter callbacks in variables that may hold values/undefined
- Prefer object-literal getters/setters (get x() {...}) over manual descriptors
When it happens
Trigger: Object.defineProperty(obj, 'k', { set: true }) or { set: null } or { set: someNonFunction }.
Common situations: Passing a stored callback variable that is actually undefined-transformed-to-null; mixing up value and set fields; descriptors round-tripped through JSON losing function identity.
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
- Getter must be a function
- Cannot set property ' ' which has only a getter
- assignment to constant
- assignment to constant
- Generator is already running
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/5428b8f1dca261c9.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsObjectConstructor.java:639
// {@code defineProperty/15.2.3.6-3-{8,13}}). Only literal undefined
// is the spec-permitted "absent" sentinel.
JsCallable newGetter = null;
JsCallable newSetter = null;
if (isAccessor) {
if (hasGet) {
Object g = descRead(descObj, descMap, "get", cc);
if (g != Terms.UNDEFINED) {
if (!(g instanceof JsCallable c)) {
throw JsErrorException.typeError("Getter must be a function");
}
newGetter = c;
}
}
if (hasSet) {
Object s = descRead(descObj, descMap, "set", cc);
if (s != Terms.UNDEFINED) {
if (!(s instanceof JsCallable c)) {
throw JsErrorException.typeError("Setter must be a function");
}
newSetter = c;
}
}
}
// A symbol key addresses the symbol store — the validation below is
// indexed by `prop`, which a symbol key does not have.
if (symKey != null) {
if (!(target instanceof JsObject jo)) {
return target;
}
PropertySlot prior = jo.ownSymbolSlot(symKey);
if (prior == null && !jo.isExtensible()) {
throw JsErrorException.typeError(
"Cannot define property " + symKey + ", object is not extensible");
}
// new keys default to all-false per ValidateAndApplyPropertyDescriptorView on GitHub (pinned to a22eb90246)