apple/pkl · error · GenericParserError
keywordNotAllowedHere
keywordNotAllowedHere
Error message
Keyword `{0}` is not allowed here. What it means
The parser throws keywordNotAllowedHere (message 'Keyword `{0}` is not allowed here.') when a Pkl keyword token appears where a module member should start. Only identifiers and the specific keywords class/typealias/function may begin a module member; any other keyword (e.g. `if`, `let`, `when`, `is`) in top-level member position is rejected, with the offending keyword text as the parameter.
Source
Thrown at pkl-parser/src/main/java/org/pkl/parser/GenericParserImpl.java:204
while (lookahead.isModifier()) {
modifiers.add(make(NodeType.MODIFIER, next().span));
hasModifier = true;
ff(children);
}
if (hasModifier) children.add(new Node(NodeType.MODIFIER_LIST, modifiers));
return new HeaderResult(hasDocComment, hasAnnotation, hasModifier);
}
private Node parseModuleMember(List<Node> preChildren) {
return switch (lookahead) {
case IDENTIFIER -> parseClassProperty(preChildren);
case TYPE_ALIAS -> parseTypeAlias(preChildren);
case CLASS -> parseClass(preChildren);
case FUNCTION -> parseClassMethod(preChildren);
case EOF -> throw parserError("unexpectedEndOfFile");
default -> {
if (lookahead.isKeyword()) {
throw parserError("keywordNotAllowedHere", lookahead.text());
}
if (lookahead == Token.DOC_COMMENT) {
throw parserError("danglingDocComment");
}
throw parserError("invalidTopLevelToken");
}
};
}
private Node parseTypeAlias(List<Node> preChildren) {
var headerParts = getHeaderParts(preChildren);
var children = new ArrayList<>(headerParts.preffixes);
var headers = new ArrayList<Node>();
if (headerParts.modifierList != null) {
headers.add(headerParts.modifierList);
}
// typealias keyword
headers.add(makeTerminal(next()));View on GitHub (pinned to f3efcbfc9b)
Solutions
- Remove the stray keyword or replace it with a valid module member declaration (property, class, typealias, or method).
- If the keyword was meant as an identifier, rename it to a non-reserved name (e.g. `when` -> `whenValue`).
- Check the surrounding lines for a deleted/merged member definition that left the keyword orphaned.
Example fix
// before
module my.mod
if (cond) { x = 1 }
// after
module my.mod
x = if (cond) 1 else 2 Defensive patterns
Strategy: validation
Validate before calling
// lint: first token of each top-level line must not be a non-member keyword
const memberKeywords = new Set(["class", "typealias", "function"]);
const reserved = new Set(["if", "let", "when", "is", "amends", "extends", "import", "module", "nothing", "unknown", "read", "output", "super", "this", "outer"]);
for (const line of pklSource.split("\n")) {
const w = line.trim().split(/\s+/)[0];
if (reserved.has(w) && !memberKeywords.has(w)) throw new Error(`Keyword ${w} not allowed at member position`);
} Prevention
- Use only property/class/typealias/function declarations at module top level.
- Avoid naming identifiers with Pkl reserved words.
- Review refactors that delete member names so no bare keyword is left behind.
When it happens
Trigger: Writing a bare keyword at top level of a .pkl module, e.g. `if` or `let` as the first token of a line in the module body, or accidentally deleting a member name so only its keyword remains (e.g. a stray `function` without a name is handled, but `is SomeType` at top level triggers this).
Common situations: Copy-pasting expression-level syntax into module scope; a botched find/replace removing an identifier and leaving its keyword; typos where a reserved word was meant to be an identifier (e.g. using `when` as a property name unquoted).
Related errors
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/f7909d299554ca5f.
Report an issue: GitHub.