apple/pkl · error · ParserError
stringIndentationMustMatchLastLine
stringIndentationMustMatchLastLine
Error message
Line must match or exceed indentation of the String's last line.
What it means
Pkl multi-line strings determine their indentation from the line containing the closing delimiter, and every subsequent content line must be indented at least as far as that common indent. When a text line following a newline starts with less whitespace than the computed common indent, the parser removes the indent and throws, highlighting just the offending line's actual indent span.
Source
Thrown at pkl-parser/src/main/java/org/pkl/parser/ParserImpl.java:1251
if (start == null) {
start = token.span;
}
end = token.span;
switch (token.token) {
case STRING_NEWLINE -> {
builder.append('\n');
isNewLine = true;
}
case STRING_ESCAPE_CONTINUATION -> isNewLine = true;
case STRING_PART -> {
var text = token.text(lexer);
if (isNewLine) {
if (text.startsWith(commonIndent)) {
builder.append(text, commonIndent.length(), text.length());
} else {
var actualIndent = getLeadingIndentCount(text);
var textSpan = token.span.move(actualIndent).grow(-actualIndent);
throw new ParserError(
ErrorMessages.create("stringIndentationMustMatchLastLine"), textSpan);
}
} else {
builder.append(text);
}
isNewLine = false;
}
default -> {
if (isNewLine && !commonIndent.isEmpty()) {
throw new ParserError(
ErrorMessages.create("stringIndentationMustMatchLastLine"), token.span);
}
builder.append(getEscapeText(token));
isNewLine = false;
}
}
}
}View on GitHub (pinned to f3efcbfc9b)
Solutions
- Re-indent the flagged line so it has at least the same leading whitespace as the closing `"""` line
- Convert all indentation in the string to the same character type (spaces vs tabs)
- Normalize the whole block's indentation so every content line aligns with or exceeds the closing delimiter's indent
- Use an editor Pkl plugin / formatter to fix multi-line string indentation automatically
Example fix
// before
msg: """
hello
world
"""
// after
msg: """
hello
world
""" Defensive patterns
Strategy: validation
Validate before calling
function checkMultilineIndent(block) {
const lines = block.split('\n');
const closer = lines[lines.length - 1];
const indent = closer.match(/^\s*/)[0];
return lines.slice(1, -1).every(l => l.trim() === '' || l.startsWith(indent));
}
// verify every content line is indented at least as far as the closing """ line Type guard
null
Try / catch
try {
const result = parser.parse(source);
} catch (e) {
if (e.errorId === 'stringIndentationMustMatchLastLine') {
// re-indent the flagged line to match the closing delimiter indent
} else { throw e; }
} Prevention
- Use spaces (not tabs) consistently inside multi-line strings
- Disable auto-dedent on save for Pkl files
- Align all content lines with the closing delimiter's indentation
When it happens
Trigger: Parsing a multi-line string where an inner line has less leading whitespace than the closing-delimiter line, e.g. content indented 2 spaces while the `"""` closer is indented 4 spaces, so the line's prefix doesn't start with commonIndent.
Common situations: Mixed tabs and spaces making one line appear shorter; an editor auto-dedenting a continuation line; hand-flattening a Pkl snippet and de-indenting the last content line above the closer.
Related errors
- stringContentMustBeginOnNewLine
- closingStringDelimiterMustBeginOnNewLine
- stringIndentationMustMatchLastLine
- Cannot parse `%s` as number.
- missingDelimiter
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/95134f9eb8fd4f76.
Report an issue: GitHub.