{"record":{"id":"95134f9eb8fd4f76","repo":"apple/pkl","slug":"stringindentationmustmatchlastline","errorCode":"stringIndentationMustMatchLastLine","errorMessage":"Line must match or exceed indentation of the String's last line.","messagePattern":"Line must match or exceed indentation of the String's last line\\.","errorType":"error_code","errorClass":"ParserError","httpStatus":null,"severity":"error","filePath":"pkl-parser/src/main/java/org/pkl/parser/ParserImpl.java","lineNumber":1251,"sourceCode":"        if (start == null) {\n          start = token.span;\n        }\n        end = token.span;\n        switch (token.token) {\n          case STRING_NEWLINE -> {\n            builder.append('\\n');\n            isNewLine = true;\n          }\n          case STRING_ESCAPE_CONTINUATION -> isNewLine = true;\n          case STRING_PART -> {\n            var text = token.text(lexer);\n            if (isNewLine) {\n              if (text.startsWith(commonIndent)) {\n                builder.append(text, commonIndent.length(), text.length());\n              } else {\n                var actualIndent = getLeadingIndentCount(text);\n                var textSpan = token.span.move(actualIndent).grow(-actualIndent);\n                throw new ParserError(\n                    ErrorMessages.create(\"stringIndentationMustMatchLastLine\"), textSpan);\n              }\n            } else {\n              builder.append(text);\n            }\n            isNewLine = false;\n          }\n          default -> {\n            if (isNewLine && !commonIndent.isEmpty()) {\n              throw new ParserError(\n                  ErrorMessages.create(\"stringIndentationMustMatchLastLine\"), token.span);\n            }\n            builder.append(getEscapeText(token));\n            isNewLine = false;\n          }\n        }\n      }\n    }","sourceCodeStart":1233,"sourceCodeEnd":1269,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-parser/src/main/java/org/pkl/parser/ParserImpl.java#L1233-L1269","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nmsg: \"\"\"\n    hello\n  world\n    \"\"\"\n// after\nmsg: \"\"\"\n    hello\n    world\n    \"\"\"","handlingStrategy":"validation","validationCode":"function checkMultilineIndent(block) {\n  const lines = block.split('\\n');\n  const closer = lines[lines.length - 1];\n  const indent = closer.match(/^\\s*/)[0];\n  return lines.slice(1, -1).every(l => l.trim() === '' || l.startsWith(indent));\n}\n// verify every content line is indented at least as far as the closing \"\"\" line","typeGuard":"null","tryCatchPattern":"try {\n  const result = parser.parse(source);\n} catch (e) {\n  if (e.errorId === 'stringIndentationMustMatchLastLine') {\n    // re-indent the flagged line to match the closing delimiter indent\n  } else { throw e; }\n}","preventionTips":["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"],"tags":["parser","pkl","indentation","multi-line-string"],"backgroundTag":"multiline-string-indentation-mismatch","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"}