{"record":{"id":"a3a807bae6bc9804","repo":"karatelabs/karate","slug":"private-name-name-is-not-declared-in-an-enclosing-class-a3a807","errorCode":null,"errorMessage":"private name ${name} is not declared in an enclosing class","messagePattern":"private name (.+?) is not declared in an enclosing class","errorType":"exception","errorClass":"JsErrorException (syntaxError)","httpStatus":null,"severity":"error","filePath":"karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java","lineNumber":41,"sourceCode":" */\npackage io.karatelabs.js;\n\n/**\n * Read / write / brand-check for {@code obj.#x}. The parser has already proved the\n * name is declared by an enclosing class body, so an unresolved name here means the\n * frame is missing its private environment rather than that the program is wrong.\n * The runtime error that IS reachable is the brand miss: the object simply is not an\n * instance of the declaring class.\n */\nfinal class PrivateAccess {\n\n    private PrivateAccess() {\n    }\n\n    static PrivateName resolve(String name, CoreContext context) {\n        PrivateName pn = context.privateEnv == null ? null : context.privateEnv.resolve(name);\n        if (pn == null) {\n            throw JsErrorException.syntaxError(\"private name \" + name + \" is not declared in an enclosing class\");\n        }\n        return pn;\n    }\n\n    static boolean has(Object target, PrivateName pn) {\n        return target instanceof JsObject obj && obj.hasPrivate(pn);\n    }\n\n    static Object get(Object target, PrivateName pn, CoreContext context) {\n        JsObject obj = branded(target, pn, \"read\");\n        return switch (pn.kind) {\n            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);","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java#L23-L59","documentation":"In Karate's JS engine, `#name` private fields are tracked per-class in a private environment. `PrivateAccess.resolve` throws this SyntaxError when a `#name` reference is evaluated but no enclosing class declared that private name, mirroring the ES spec requirement that private names must be lexically declared in a surrounding class.","triggerScenarios":"Evaluating a JS expression that references a private name (e.g. `this.#count`) from code that is not lexically inside a class declaring `#count`, or referencing a private field of a class that only exists at runtime as a value (no enclosing declaration).","commonSituations":"Copy-pasting class methods out of their class body into standalone functions; calling a method that uses `#field` via `.call()`/function reassignment outside the class; typos in the private name (`#Count` vs `#count`).","solutions":["Declare the private name inside the enclosing class (add `#count;` or the field/method in the class body).","Fix typos so the referenced private name exactly matches the declaration.","Move the code back inside the class body so it is lexically enclosed by the declaration.","If the field does not need privacy, convert `#name` to a normal property."],"exampleFix":"// before\nconst f = obj.increment; // method using this.#count escapes class\nf(); // SyntaxError: private name #count is not declared in an enclosing class\n// after\nobj.increment(); // called with proper class context / declare #count in the class body","handlingStrategy":"validation","validationCode":"// before referencing #name, ensure the code is lexically inside the declaring class\nfunction usesPrivateName(src, name) {\n  return new RegExp('class[^{]*\\\\{[\\\\s\\\\S]*#' + name + '\\\\b').test(src);\n}\nif (!usesPrivateName(classSource, 'count')) throw new Error('#count not declared in enclosing class');","typeGuard":"function isInClassBody(fn) { return /class[\\s\\S]*#[A-Za-z_$]/.test(String(fn)); }","tryCatchPattern":"try { engine.eval(js); } catch (e) { if (String(e.message).includes('not declared in an enclosing class')) { /* fix source: declare the private name */ } else { throw e; } }","preventionTips":["Keep all `#name` references inside the class body that declares them.","Avoid extracting private-name-using methods out of the class.","Lint for `#name` usage outside class scopes.","Double-check private name spelling matches the declaration."],"tags":["javascript","private-fields","syntax-error","classes"],"backgroundTag":"invalid-identifier-format","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"}