apple/pkl · error
invalidCharacter
invalidCharacter
Error message
Invalid identifier `{0}`. What it means
The lexer's default branch cannot classify the character: it is not a digit and not a valid identifier start, so it reports "Invalid identifier" with the offending character via lexError keyed as invalidCharacter. This covers stray punctuation, unicode look-alikes, and control characters in Pkl source.
Solutions
- Replace the offending character with its ASCII equivalent (straight quotes, regular spaces).
- Quote the text as a string literal if it is data, not code.
- Re-save the file as clean UTF-8 without BOM; strip invisible characters.
- Check for language-specific syntax (e.g. decorators `@`) that Pkl does not support in that position.
Example fix
// before (smart quotes) name = “pkl” // after name = "pkl"
Defensive patterns
Strategy: validation
Validate before calling
function findNonAsciiCodeChars(src) {
const issues = [];
const lines = src.split("\n");
lines.forEach((line, i) => {
const cleaned = line.replace(/"[^"]*"/g, ""); // ignore string contents
const bad = cleaned.match(/[^\x20-\x7E\t]/g);
if (bad) issues.push({ line: i + 1, chars: bad.map(c => c.codePointAt(0).toString(16)) });
});
return issues;
} Prevention
- Configure editors to insert straight quotes and flag smart quotes in code files.
- Save as UTF-8 without BOM; strip non-breaking spaces on paste.
- Pre-commit hook running a lexer check (pkl eval) on all .pkl files.
When it happens
Trigger: A character that can't start a token appears in code — e.g. `@` outside annotations, `#` outside custom string delimiters, smart quotes from a word processor (`“` instead of `"`), non-breaking spaces, or emoji in unquoted positions.
Common situations: Copying code from docs/slack that converted quotes to smart quotes; invisible BOM or non-breaking space characters; writing DSL-like syntax from another language; stray comment markers.
Related errors
- Unexpected character
- Unexpected character
- unexpectedCharacter
- unexpectedEndOfFile
- unterminatedUnicodeEscapeSequence
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/e1d655d418dbd34c.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-parser/src/main/java/org/pkl/parser/Lexer.java:263
case '`' -> {
lexQuotedIdentifier();
yield Token.IDENTIFIER;
}
case '/' -> lexSlash();
case '"' -> lexStringStart(0);
case '#' -> {
if (lookahead == '!') {
yield lexShebang();
} else {
yield lexStringStartPounds();
}
}
default -> {
if (Character.isDigit(ch)) {
yield lexNumber(ch);
} else if (isIdentifierStart(ch)) {
yield lexIdentifier();
} else throw lexError(ErrorMessages.create("invalidCharacter", (char) ch), cursor - 1, 1);
}
};
}
private Token nextString() {
var scope = interpolationStack.getFirst();
if (stringEnded) {
lexStringEnd(scope);
stringEnded = false;
interpolationStack.pop();
state = State.DEFAULT;
return Token.STRING_END;
}
if (lookahead == EOF) return Token.EOF;
if (isEscape) {
isEscape = false;
// consume the `\#*`
for (var i = 0; i < scope.pounds + 1; i++) {View on GitHub (pinned to f3efcbfc9b)