karatelabs/karate · error · ParserException
private name is not declared in an enclosing class
Error message
private name ${name} is not declared in an enclosing class What it means
A private name may only be used inside the class (or nested class) whose body declares it. Karate tracks PrivateScope objects per class body during parsing; when a private name is referenced (or a member key resolves) but the enclosing scope chain has no class declaring that name, requirePrivateDeclared throws this early error.
Solutions
- Declare the private name in the enclosing class body (e.g. `class C { #x; ... }`)
- Fix the spelling of the private name to match its declaration
- Move the usage inside the class that declares the private name
Example fix
// before
class C { m() { return #x in this; } }
// after
class C { #x; m() { return #x in this; } } Defensive patterns
Strategy: validation
Validate before calling
// Verify every referenced #name is declared in the class body: const used = new Set(js.match(/#\w+/g) || []); const declared = new Set((js.match(/\s#\w+\s*[=;(]/g) || []).map(s => s.trim().split(/\s|\b/)[0]));
Try / catch
try { eval(js); } catch (e) { if (String(e).includes('is not declared in an enclosing class')) { /* declare the private name in the class */ } throw e; } Prevention
- Declare private fields at the top of the class body
- Check spelling of private names against declarations
- Keep private-member usage inside the declaring class
When it happens
Trigger: Referencing `#x` (in an `in` check, member access, or declaration-dependent position) when privates is null (not inside any class body) or the enclosing PrivateScope does not declare the name — e.g. using a private name of an outer class from unrelated code, or a typo in the private name.
Common situations: Typos in private names (`#lenght` vs `#length`), using private members outside the class body, copy-pasting methods between classes where the target class lacks the private declaration.
Related errors
- unexpected private name
- cannot delete private member
- label already in scope
- unexpected logical-assignment operator
- unexpected operator
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/da33b7178e1c5f99.
Report an issue: GitHub.
Appendix: source
Thrown at karate-js/src/main/java/io/karatelabs/parser/JsParser.java:315
}
if (target.type == NodeType.PAREN_EXPR) {
target = target.size() > 1 ? target.get(1) : null;
} else if (target.type == NodeType.EXPR || target.type == NodeType.EXPR_LIST) {
target = target.size() == 1 ? target.getFirst() : null;
} else {
break;
}
}
}
default -> {
}
}
return privates;
}
private static void requirePrivateDeclared(String name, PrivateScope privates) {
if (privates == null || !privates.declares(name)) {
throw new ParserException("private name " + name + " is not declared in an enclosing class");
}
}
/** Collects the {@code #name} keys declared directly by a class body. Each
* CLASS_METHOD holds its key as a direct token child, so at most one
* PRIVATE_NAME can appear per member (an initializer lives in a nested EXPR). */
private static PrivateScope classPrivateScope(Node classNode, PrivateScope parent) {
Set<String> names = null;
Map<String, Integer> kinds = null;
for (int i = 0, n = classNode.size(); i < n; i++) {
Node member = classNode.get(i);
if (member.type != NodeType.CLASS_METHOD) {
continue;
}
Node key = null;
int kind = 4; // 1 = get, 2 = set, 4 = anything else; 8 = static
for (int j = 0, m = member.size(); j < m; j++) {
Node c = member.get(j);View on GitHub (pinned to a22eb90246)