apple/pkl · error
Unexpected character
Error message
Unexpected character `{0}`. Did you mean `{1}`? What it means
The lexer's nextDefault() sees a lone `&` character, which is not a valid Pkl token by itself. Pkl only defines the `&&` logical-and operator, so the lexer suggests `&&` via unexpectedChar(). This is a lexical scan error raised before any parsing occurs.
Solutions
- Replace `&` with `&&` if a logical-and was intended.
- Remove the stray `&` if it is a typo.
- Move the character into a string literal or comment if it was meant as data.
Example fix
// before if (a & b) ... // after if (a && b) ...
Defensive patterns
Strategy: validation
Validate before calling
function assertNoSingleAmpersand(src) {
const bad = src.replace(/&&/g, "").match(/&/);
if (bad) throw new Error(`Lone '&' at index ${bad.index}; use '&&'`);
} Prevention
- Remember Pkl has no bitwise `&`; only `&&` exists.
- Quote any content containing ampersands as string literals.
- Sanitize pasted code from C-family languages before embedding in Pkl.
When it happens
Trigger: Writing a single `&` in Pkl source — e.g. a bitwise-and habit from other languages, a typo writing `&&` as `&`, or an ampersand inside code that wasn't quoted or commented.
Common situations: Translating Java/C/TypeScript expressions to Pkl; shell scripts or YAML with unescaped `&` pasted into Pkl; template escaping mistakes.
Related errors
- Unexpected character
- invalidCharacter
- unexpectedEndOfFile
- '" + ch + "'
- closingStringDelimiterMustBeginOnNewLine
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/f813a567c45796e5.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-parser/src/main/java/org/pkl/parser/Lexer.java:197
nextChar();
yield Token.NOT_EQUAL;
} else yield Token.NOT;
}
case '?' -> {
if (lookahead == '.') {
nextChar();
yield Token.QDOT;
} else if (lookahead == '?') {
nextChar();
yield Token.COALESCE;
} else yield Token.QUESTION;
}
case '&' -> {
if (lookahead == '&') {
nextChar();
yield Token.AND;
} else {
throw unexpectedChar(ch, "&&");
}
}
case '|' -> {
if (lookahead == '>') {
nextChar();
yield Token.PIPE;
} else if (lookahead == '|') {
nextChar();
yield Token.OR;
} else {
yield Token.UNION;
}
}
case '*' -> {
if (lookahead == '*') {
nextChar();
yield Token.POW;
} else yield Token.STAR;View on GitHub (pinned to f3efcbfc9b)