{"record":{"id":"c5ece4614d491a6d","repo":"karatelabs/karate","slug":"getter-must-be-a-function","errorCode":null,"errorMessage":"Getter must be a function","messagePattern":"Getter must be a function","errorType":"exception","errorClass":"JsErrorException","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/JsObjectConstructor.java","lineNumber":630,"sourceCode":"        // the perpetually-extensible default and pass through.\n        if (symKey == null && !keyExists && target instanceof ObjectLike ol && !ol.isExtensible()) {\n            throw JsErrorException.typeError(\"Cannot define property \" + prop + \", object is not extensible\");\n        }\n\n        // Validate accessor shapes early so we can fall through to the unified write below.\n        // Spec ToPropertyDescriptor §6.2.5.5: if Get/Set is present but not\n        // {@code undefined} AND not callable, throw TypeError. {@code null}\n        // is a non-callable non-undefined value — must throw (test262\n        // {@code defineProperty/15.2.3.6-3-{8,13}}). Only literal undefined\n        // is the spec-permitted \"absent\" sentinel.\n        JsCallable newGetter = null;\n        JsCallable newSetter = null;\n        if (isAccessor) {\n            if (hasGet) {\n                Object g = descRead(descObj, descMap, \"get\", cc);\n                if (g != Terms.UNDEFINED) {\n                    if (!(g instanceof JsCallable c)) {\n                        throw JsErrorException.typeError(\"Getter must be a function\");\n                    }\n                    newGetter = c;\n                }\n            }\n            if (hasSet) {\n                Object s = descRead(descObj, descMap, \"set\", cc);\n                if (s != Terms.UNDEFINED) {\n                    if (!(s instanceof JsCallable c)) {\n                        throw JsErrorException.typeError(\"Setter must be a function\");\n                    }\n                    newSetter = c;\n                }\n            }\n        }\n\n        // A symbol key addresses the symbol store — the validation below is\n        // indexed by `prop`, which a symbol key does not have.\n        if (symKey != null) {","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/JsObjectConstructor.java#L612-L648","documentation":"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.","triggerScenarios":"Object.defineProperty(obj, 'k', { get: 123, enumerable: true }) or { get: null } — a present, non-undefined, non-callable 'get' value.","commonSituations":"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.","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"],"exampleFix":"// before\nObject.defineProperty(o, 'x', { get: null });\n// after\nObject.defineProperty(o, 'x', { get() { return this._x; } });","handlingStrategy":"type-guard","validationCode":"if (desc.get !== undefined && typeof desc.get !== 'function') throw new TypeError('get must be a function or undefined');","typeGuard":"function hasValidGetter(desc) { return !('get' in desc) || desc.get === undefined || typeof desc.get === 'function'; }","tryCatchPattern":"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; }","preventionTips":["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"],"tags":["javascript","descriptor","accessor","typeerror"],"backgroundTag":"invalid-argument-value","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}