apple/pkl · error · ParserError
stringContentMustBeginOnNewLine
stringContentMustBeginOnNewLine
Error message
The content of a multi-line string must begin on a new line.
What it means
In a Pkl multi-line string ("""..."""), the content is required to start on its own line after the opening delimiter. The parser validates the parsed string nodes and throws when the very first node is not a newline token, i.e. content immediately follows the opening triple quote. This rule keeps multi-line strings free of the opening delimiter's indentation.
Source
Thrown at pkl-parser/src/main/java/org/pkl/parser/ParserImpl.java:1200
case EOF -> {
var delimiter = new StringBuilder(start.text(lexer)).reverse().toString();
throw parserError("missingDelimiter", delimiter);
}
}
}
var end = next().span;
var fullSpan = start.span.endWith(end);
var parts = validateMultiLineString(stringTokens, fullSpan);
return new MultiLineStringLiteralExpr(parts, start.span, end, fullSpan);
}
private List<StringPart> validateMultiLineString(List<TempNode> nodes, Span span) {
var firstNode = nodes.isEmpty() ? null : nodes.get(0);
if (firstNode == null
|| firstNode.token == null
|| firstNode.token.token != Token.STRING_NEWLINE) {
var errorSpan = firstNode == null ? span : firstNode.span();
throw new ParserError(ErrorMessages.create("stringContentMustBeginOnNewLine"), errorSpan);
}
// only contains a newline
if (nodes.size() == 1) {
return List.of(new StringChars("", firstNode.span()));
}
var indent = getCommonIndent(nodes, span);
return renderString(nodes, indent);
}
private List<StringPart> renderString(List<TempNode> nodes, String commonIndent) {
var parts = new ArrayList<StringPart>();
var builder = new StringBuilder();
var lastToken = nodes.get(nodes.size() - 1).token;
assert lastToken != null;
var endOffset = lastToken.token == Token.STRING_NEWLINE ? 1 : 2;
var isNewLine = true;
Span start = null;
Span end = null;View on GitHub (pinned to f3efcbfc9b)
Solutions
- Put a line break immediately after the opening `"""` delimiter so content starts on the next line
- Indent the string content; Pkl strips the common indentation automatically
- If a single-line value was intended, use a normal quoted string instead of a multi-line one
Example fix
// before msg: """hello // after msg: """ hello """
Defensive patterns
Strategy: validation
Validate before calling
function multilineStringOpensOnNewLine(line) {
const m = line.match(/"""(.*)$/);
return !(m && m[1].trim() !== ''); // true if opening """ is alone on its line
}
// scan each line of the .pkl source containing '"""' before parsing Type guard
null
Try / catch
try {
const result = parser.parse(source);
} catch (e) {
if (e.errorId === 'stringContentMustBeginOnNewLine') {
// suggest inserting a newline after the opening triple quote at e.span
} else { throw e; }
} Prevention
- Always put content on the line after the opening """
- Use a Pkl formatter/IDE plugin for multi-line strings
- Prefer single-quoted strings for one-line values
When it happens
Trigger: Parsing source where a multi-line string is opened like `text: """hello` with content on the same line as the opening `"""`, or where the string is empty/malformed such that no STRING_NEWLINE token starts the content list.
Common situations: Developers used to Kotlin/Scala raw strings writing `"""text` on one line; converting YAML or heredocs to Pkl; editor snippets that collapse the newline after the opening delimiter.
Related errors
- closingStringDelimiterMustBeginOnNewLine
- missingDelimiter
- unexpectedEndOfFile
- stringIndentationMustMatchLastLine
- notAUnion
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/5191731393ce2228.
Report an issue: GitHub.