apple/pkl · error · GenericParserError
interpolationInConstant
interpolationInConstant
Error message
String constant cannot have interpolated values.
What it means
Pkl string constants (plain quoted strings) do not support `\(...)` interpolation; only standard strings may interpolate. When the parser encounters INTERPOLATION_START inside a string constant it throws this dedicated error. This distinguishes constant strings (which are interned/exact) from interpolating strings.
Solutions
- Use Pkl's standard string interpolation form `"\(expr)"` in a regular (non-constant) string context.
- Concatenate values explicitly if the context requires a constant: `"a " + x`.
- Remove the interpolation and hardcode the value if the string must remain constant.
Example fix
// before (in a string-constant position) greeting = "Hello \(name)" // after greeting = "Hello " + name
Defensive patterns
Strategy: validation
Validate before calling
function assertNoInterpolationInConstant(str, isConstantContext) {
if (isConstantContext && /\\\(/.test(str)) {
throw new Error(`String constant cannot interpolate: ${str}`);
}
} Prevention
- Know which Pkl positions accept constants (annotations, some defaults) and keep them static.
- Use concatenation (`"a " + expr`) instead of `\(...)` when in doubt.
- Lint generated Pkl for `\(` inside constant contexts.
When it happens
Trigger: Using `\(expr)` inside a string constant produced in parseStringConstant(), e.g. `const = "value \(x)"` in a context where the string is lexed as a constant (such as certain module-level or annotation contexts).
Common situations: Porting Kotlin/Swift-style interpolation habits into Pkl constant strings; moving a string between contexts where the lexer classifies it differently; assuming all Pkl strings interpolate.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- '" + ch + "'
- closingStringDelimiterMustBeginOnNewLine
- closingStringDelimiterMustBeginOnNewLine
- ':'
- ErrorMessages.create(errorKey, args)
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/b209455b2e93adf9.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-parser/src/main/java/org/pkl/parser/GenericParserImpl.java:1396
private Node parseStringConstant() {
var children = new ArrayList<Node>();
var startTk = expect(Token.STRING_START, "unexpectedToken", "\"");
children.add(makeTerminal(startTk));
while (lookahead != Token.STRING_END) {
switch (lookahead) {
case STRING_PART,
STRING_ESCAPE_NEWLINE,
STRING_ESCAPE_TAB,
STRING_ESCAPE_QUOTE,
STRING_ESCAPE_BACKSLASH,
STRING_ESCAPE_RETURN,
STRING_ESCAPE_UNICODE ->
children.add(makeTerminal(next()));
case EOF -> {
var delimiter = new StringBuilder(startTk.text(lexer)).reverse().toString();
throw parserError("missingDelimiter", delimiter);
}
case INTERPOLATION_START -> throw parserError("interpolationInConstant");
// the lexer makes sure we only get the above tokens inside a string
default -> throw new RuntimeException("Unreacheable code");
}
}
children.add(makeTerminal(next())); // string end
return new Node(NodeType.STRING_CHARS, children);
}
private FullToken expect(Token type, String errorKey, Object... messageArgs) {
if (lookahead != type) {
var span = spanLookahead;
if (lookahead == Token.EOF || _lookahead.newLinesBetween > 0) {
// don't point at the EOF or the next line, but at the end of the last token
span = prev().span.stopSpan();
}
var args = messageArgs;
if (errorKey.startsWith("unexpectedToken")) {
args = new Object[messageArgs.length + 1];View on GitHub (pinned to f3efcbfc9b)