karatelabs/karate · error · JsErrorException (syntaxError)
private name is not declared in an enclosing class
Error message
private name ${name} is not declared in an enclosing class What it means
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.
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.
Example fix
// before const f = obj.increment; // method using this.#count escapes class f(); // SyntaxError: private name #count is not declared in an enclosing class // after obj.increment(); // called with proper class context / declare #count in the class body
Defensive patterns
Strategy: validation
Validate before calling
// before referencing #name, ensure the code is lexically inside the declaring class
function usesPrivateName(src, name) {
return new RegExp('class[^{]*\\{[\\s\\S]*#' + name + '\\b').test(src);
}
if (!usesPrivateName(classSource, 'count')) throw new Error('#count not declared in enclosing class'); Type guard
function isInClassBody(fn) { return /class[\s\S]*#[A-Za-z_$]/.test(String(fn)); } Try / catch
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; } } Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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`).
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- unexpected private name
- unexpected private name
- ${hint: names offending unquoted object-literal keys…
- parser state: [ ]
- cannot delete private member
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/a3a807bae6bc9804.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/js/PrivateAccess.java:41
*/
package io.karatelabs.js;
/**
* Read / write / brand-check for {@code obj.#x}. The parser has already proved the
* name is declared by an enclosing class body, so an unresolved name here means the
* frame is missing its private environment rather than that the program is wrong.
* The runtime error that IS reachable is the brand miss: the object simply is not an
* instance of the declaring class.
*/
final class PrivateAccess {
private PrivateAccess() {
}
static PrivateName resolve(String name, CoreContext context) {
PrivateName pn = context.privateEnv == null ? null : context.privateEnv.resolve(name);
if (pn == null) {
throw JsErrorException.syntaxError("private name " + name + " is not declared in an enclosing class");
}
return pn;
}
static boolean has(Object target, PrivateName pn) {
return target instanceof JsObject obj && obj.hasPrivate(pn);
}
static Object get(Object target, PrivateName pn, CoreContext context) {
JsObject obj = branded(target, pn, "read");
return switch (pn.kind) {
case FIELD -> obj.getPrivate(pn);
case METHOD -> pn.method;
case ACCESSOR -> {
if (pn.getter == null) {
throw JsErrorException.typeError("'" + pn.name + "' was defined without a getter");
}
yield Interpreter.invokeGetter(pn.getter, target, context);View on GitHub (pinned to a22eb90246)