{"record":{"id":"5b2a3d69be7e2494","repo":"karatelabs/karate","slug":"pn-name-was-defined-without-a-setter","errorCode":null,"errorMessage":"'${pn.name}' was defined without a setter","messagePattern":"'(.+?)' was defined without a setter","errorType":"exception","errorClass":"JsErrorException (typeError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java","lineNumber":71,"sourceCode":"            case FIELD -> obj.getPrivate(pn);\n            case METHOD -> pn.method;\n            case ACCESSOR -> {\n                if (pn.getter == null) {\n                    throw JsErrorException.typeError(\"'\" + pn.name + \"' was defined without a getter\");\n                }\n                yield Interpreter.invokeGetter(pn.getter, target, context);\n            }\n        };\n    }\n\n    static void set(Object target, PrivateName pn, Object value, CoreContext context) {\n        JsObject obj = branded(target, pn, \"write\");\n        switch (pn.kind) {\n            case FIELD -> obj.putPrivate(pn, value);\n            case METHOD -> throw JsErrorException.typeError(\"Cannot write to private method \" + pn.name);\n            case ACCESSOR -> {\n                if (pn.setter == null) {\n                    throw JsErrorException.typeError(\"'\" + pn.name + \"' was defined without a setter\");\n                }\n                Interpreter.invokeSetter(pn.setter, target, value, context);\n            }\n        }\n    }\n\n    private static JsObject branded(Object target, PrivateName pn, String verb) {\n        if (target instanceof JsObject obj && obj.hasPrivate(pn)) {\n            return obj;\n        }\n        throw JsErrorException.typeError(\"Cannot \" + verb + \" private member \" + pn.name\n                + \" from an object whose class did not declare it\");\n    }\n\n}\n","sourceCodeStart":53,"sourceCodeEnd":87,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java#L53-L87","documentation":"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.","triggerScenarios":"Assigning `obj.#prop = value` where the class declared `accessor #prop` (or an accessor pair) without a `set` accessor.","commonSituations":"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).","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."],"exampleFix":"// before\nclass C { get #x() { return 1; } }\nnew C().#x = 2; // TypeError: '#x' was defined without a setter\n// after\nclass C { #x = 1; } // or add: set #x(v) { ... }","handlingStrategy":"validation","validationCode":"// verify a setter exists before assigning to a private accessor\nconst hasSetter = /set\\s+#prop\\b|accessor\\s+#prop\\b/.test(classSource);","typeGuard":"function privateAccessorWritable(classSrc, name) { return new RegExp('(set\\\\s+#' + name + '|accessor\\\\s+#' + name + ')').test(classSrc); }","tryCatchPattern":"try { obj.#prop = v; } catch (e) { if (e instanceof TypeError && e.message.includes('without a setter')) { /* write underlying field instead */ } else { throw e; } }","preventionTips":["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."],"tags":["javascript","private-fields","type-error","accessor"],"backgroundTag":"unsupported-operation","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"}