{"record":{"id":"b649aba762870917","repo":"apple/pkl","slug":"missingdelimiter-b649ab","errorCode":"missingDelimiter","errorMessage":"Missing `{0}` delimiter.","messagePattern":"Missing `(.+?)` delimiter\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkl-parser/src/main/java/org/pkl/parser/Lexer.java","lineNumber":354,"sourceCode":"    return Token.STRING_MULTI_START;\n  }\n\n  private void lexStringEnd(InterpolationScope scope) {\n    // don't actually need to check it here\n    for (var i = 0; i < scope.quotes + scope.pounds; i++) {\n      nextChar();\n    }\n  }\n\n  private void lexString(int pounds) {\n    var poundsInARow = 0;\n    var foundQuote = false;\n    var foundBackslash = false;\n    while (lookahead != EOF) {\n      var ch = nextChar();\n      switch (ch) {\n        case '\\n', '\\r' ->\n            throw lexError(\n                ErrorMessages.create(\"missingDelimiter\", \"\\\"\" + \"#\".repeat(pounds)), cursor - 1, 1);\n        case '\"' -> {\n          if (pounds == 0) {\n            backup();\n            stringEnded = true;\n            return;\n          }\n          foundQuote = true;\n          foundBackslash = false;\n          poundsInARow = 0;\n        }\n        case '\\\\' -> {\n          foundQuote = false;\n          foundBackslash = true;\n          poundsInARow = 0;\n          if (pounds == poundsInARow) {\n            backup(pounds + 1);\n            isEscape = true;","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-parser/src/main/java/org/pkl/parser/Lexer.java#L336-L372","documentation":"A string literal was opened but the matching closing delimiter (a `\"` preceded by the same number of `#` as the opening) was never found on the same line. Pkl single-line strings cannot contain raw newlines, so when the lexer hits a newline or carriage return inside the string body it throws missingDelimiter. The expected delimiter text includes the `#` repetition for multi-line `#\"...\"#` strings.","triggerScenarios":"nextString → lexString: while scanning the body of a string, the lexer reaches a `\\n` or `\\r` before encountering the closing `\"` (with matching `#` pounds), or encounters EOF. Any raw line break inside a single-line string literal triggers it.","commonSituations":"Forgetting to close a string before pressing Enter; intending a multi-line string but writing `\"...` instead of `\"\"\"...` (triple-quote) form; copy-paste splitting a long string across lines without concatenation; mismatched `#` counts between opening and closing of `#\"...\"#`.","solutions":["Add the closing `\"` (with the same `#` prefix if opened as `#\"`) on the same line.","Use a multi-line string (`\"\"\"` form) if the value must span lines.","Escape the newline with `\\` line continuation or use string concatenation (`+`).","Check for a stray unmatched quote earlier in the line that swallowed the real closing quote."],"exampleFix":"// before\ngreeting = \"hello\nworld\"\n// after\ngreeting = \"\"\"\nhello\nworld\n\"\"\"","handlingStrategy":"validation","validationCode":"function singleLineStringsClosed(line) { const q = (line.match(/(?<!\\\\)\"/g) || []).length; return q % 2 === 0; }\nif (!pklLines.every(singleLineStringsClosed)) throw new Error('Unbalanced quotes in single-line string');","typeGuard":"null","tryCatchPattern":"try { tokens = lexer.next(); } catch (e) { if (e.code === 'missingDelimiter') { console.error(`Unterminated string at line ${e.line}`); } throw e; }","preventionTips":["Use triple-quoted \"\"\" strings for values spanning multiple lines.","Enable editor highlighting for string literals to spot unterminated strings.","Check # counts match on both ends of #-delimited strings.","Never put raw newlines inside single-line string literals."],"tags":["lexer","pkl","string-literal","unterminated"],"backgroundTag":"missing-delimiter","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}