karatelabs/karate · error · JsErrorException
Getter must be a function
Error message
Getter must be a function
What it means
When a property descriptor passed to Object.defineProperty() includes a 'get' field, that field must be a callable function or undefined. Any other value (including null) is rejected per spec ToPropertyDescriptor with a TypeError.
Solutions
- Pass an actual function to get: (obj, 'k', { get() { return this._k; } })
- Remove the get field entirely if you meant a data descriptor (use value/writable)
- Check for undefined vs null: use undefined (or omit the key), never null
- Verify the value is typeof 'function' before building the descriptor
Example fix
// before
Object.defineProperty(o, 'x', { get: null });
// after
Object.defineProperty(o, 'x', { get() { return this._x; } }); Defensive patterns
Strategy: type-guard
Validate before calling
if (desc.get !== undefined && typeof desc.get !== 'function') throw new TypeError('get must be a function or undefined'); Type guard
function hasValidGetter(desc) { return !('get' in desc) || desc.get === undefined || typeof desc.get === 'function'; } Try / catch
try { Object.defineProperty(o, k, desc); } catch (e) { if (String(e.message).includes('Getter must be a function')) console.error('descriptor.get =', desc.get); else throw e; } Prevention
- Never use null for absent accessors — omit the key or use undefined
- Keep descriptor builders typed (JSDoc/TS: PropertyDescriptor)
- Do not serialize descriptors through JSON — functions are lost
When it happens
Trigger: Object.defineProperty(obj, 'k', { get: 123, enumerable: true }) or { get: null } — a present, non-undefined, non-callable 'get' value.
Common situations: Typo passing a property name instead of a function; refactoring from data descriptors to accessors and leaving a stale value in 'get'; JSON-serialized descriptors where functions became null.
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
- Setter 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/c5ece4614d491a6d.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/JsObjectConstructor.java:630
// the perpetually-extensible default and pass through.
if (symKey == null && !keyExists && target instanceof ObjectLike ol && !ol.isExtensible()) {
throw JsErrorException.typeError("Cannot define property " + prop + ", object is not extensible");
}
// Validate accessor shapes early so we can fall through to the unified write below.
// Spec ToPropertyDescriptor §6.2.5.5: if Get/Set is present but not
// {@code undefined} AND not callable, throw TypeError. {@code null}
// is a non-callable non-undefined value — must throw (test262
// {@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) {View on GitHub (pinned to a22eb90246)