apple/pkl · error · ParserError
unterminatedUnicodeEscapeSequence
unterminatedUnicodeEscapeSequence
Error message
Unterminated Unicode escape sequence `{0}`.
Unicode escape sequences must end with `}`. What it means
A unicode escape `\u{...}` was opened but the closing `}` was never found: the lexer scanned letters/digits after `{` and hit EOF (or a non-alphanumeric character that stopped the loop without reaching `}`). The message reports the partially-read escape text and states the sequence must end with `}`.
Source
Thrown at pkl-parser/src/main/java/org/pkl/parser/Lexer.java:504
throw lexError(
ErrorMessages.create("invalidCharacterEscapeSequence", "\\" + (char) ch, "\\"),
cursor - 2,
2);
};
}
private Token lexUnicodeEscape() {
if (lookahead != '{') {
throw unexpectedChar(lookahead, "{");
}
do {
nextChar();
} while (lookahead != '}' && lookahead != EOF && Character.isLetterOrDigit(lookahead));
if (lookahead == '}') {
// consume the close bracket
nextChar();
} else {
throw lexError(ErrorMessages.create("unterminatedUnicodeEscapeSequence", text()), span());
}
return Token.STRING_ESCAPE_UNICODE;
}
private Token lexIdentifier() {
while (isIdentifierPart(lookahead)) {
nextChar();
}
var identifierStr = text();
var identifier = getKeywordOrIdentifier(identifierStr);
return switch (identifier) {
case IMPORT -> {
if (lookahead == '*') {
nextChar();
yield Token.IMPORT_STAR;
} else yield Token.IMPORT;
}View on GitHub (pinned to f3efcbfc9b)
Solutions
- Add the closing `}` to the unicode escape: `\u{1F600}`.
- Remove any non-alphanumeric characters (spaces, hyphens) inside the braces — codepoints are hex digits only.
- If the escape is at end of file, restore the truncated file content.
- If a literal `{` should follow `\u`, escape the backslash: `\\u{`.
Example fix
// before
emoji = "\u{1F600"
// after
emoji = "\u{1F600}" Defensive patterns
Strategy: validation
Validate before calling
function unterminatedUnicode(src) { return /\\u\{[0-9A-Fa-f]*$/.test(src) || /\\u\{[^}]*\s/.test(src); }
if (unterminatedUnicode(src)) throw new Error('Unicode escape missing closing } or contains invalid chars'); Type guard
null
Try / catch
try { tokens = lexer.next(); } catch (e) { if (e.code === 'unterminatedUnicodeEscapeSequence') { console.error('Add closing } to the unicode escape'); } throw e; } Prevention
- Always type both braces at once when writing \u escapes.
- Keep only hex digits inside the braces, no spaces or hyphens.
- Check template generators emit complete escapes.
- Avoid end-of-file string content containing partial escapes.
When it happens
Trigger: lexEscape → lexUnicodeEscape: after consuming `\u{`, the loop `while (lookahead != '}' && lookahead != EOF && isLetterOrDigit(lookahead))` exits with lookahead == EOF (or a non-alphanumeric char that is not `}`), e.g. `"\u{1F600"` at end of string/file, or `"\u{12 34}"` where a space breaks the scan before `}`.
Common situations: Copy-paste truncation cutting off the closing brace; typing `\u{41}` and forgetting `}`; inserting a space or punctuation inside the codepoint like `\u{1F 600}`; a template generator emitting partial escapes.
Related errors
- unexpectedCharacter
- invalidUnicodeEscapeSequence
- missingDelimiter
- invalidLineContinuationEscapeSequenceWhitespace
- invalidCharacterEscapeSequence
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/46b6f9e5deb9d2b2.
Report an issue: GitHub.