From 175e2b627398cae04d0f763e82470033551c5499 Mon Sep 17 00:00:00 2001 From: David Tesler Date: Fri, 24 Jul 2026 13:57:05 -0700 Subject: [PATCH] Fix negative caret width rendering multi-line expression errors (#1793) The expression preamble length was subtracted from endColumn even when endColumn came from the already-stripped sourceLine.length(), so multi-line frames got a negative caret width and String.repeat threw. Apply the offset only to the frame-derived columns. --------- Co-authored-by: Dan Chao --- .../pkl/core/runtime/StackTraceRenderer.java | 10 ++---- .../org/pkl/core/EvaluateExpressionTest.kt | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/pkl-core/src/main/java/org/pkl/core/runtime/StackTraceRenderer.java b/pkl-core/src/main/java/org/pkl/core/runtime/StackTraceRenderer.java index a7dca0c55..7f697261e 100644 --- a/pkl-core/src/main/java/org/pkl/core/runtime/StackTraceRenderer.java +++ b/pkl-core/src/main/java/org/pkl/core/runtime/StackTraceRenderer.java @@ -128,17 +128,13 @@ public final class StackTraceRenderer { sourceLine = sourceLine.substring(PREAMBLE_LENGTH); hasPreamble = true; } - var startColumn = frame.getStartColumn() - leadingWhitespace; + var preambleOffset = hasPreamble ? PREAMBLE_LENGTH : 0; + var startColumn = frame.getStartColumn() - leadingWhitespace - preambleOffset; var endColumn = frame.getStartLine() == frame.getEndLine() - ? frame.getEndColumn() - leadingWhitespace + ? frame.getEndColumn() - leadingWhitespace - preambleOffset : sourceLine.length(); - if (hasPreamble) { - startColumn -= PREAMBLE_LENGTH; - endColumn -= PREAMBLE_LENGTH; - } - var prefix = frame.getStartLine() + " | "; out.append(AnsiTheme.STACK_TRACE_MARGIN, leftMargin) .append(AnsiTheme.STACK_TRACE_LINE_NUMBER, prefix); diff --git a/pkl-core/src/test/kotlin/org/pkl/core/EvaluateExpressionTest.kt b/pkl-core/src/test/kotlin/org/pkl/core/EvaluateExpressionTest.kt index 3e3f0574a..8a437d178 100644 --- a/pkl-core/src/test/kotlin/org/pkl/core/EvaluateExpressionTest.kt +++ b/pkl-core/src/test/kotlin/org/pkl/core/EvaluateExpressionTest.kt @@ -165,6 +165,40 @@ class EvaluateExpressionTest { ) } + @Test + fun `evaluate throwing multi-line expression renders without crashing`() { + val error = + assertThrows { + evaluate( + "x = 1", + """ + let (_a = 1) + let (_b = 2) + throw("boom") + """ + .trimIndent(), + ) + } + + assertThat(error.message) + .isEqualTo( + """ + –– Pkl Error –– + boom + + 3 | throw("boom") + ^^^^^^^^^^^^^ + at (repl:text) + + 1 | let (_a = 1) + ^^^^^^^^^^^^ + at repl:text. (repl:text) + + """ + .trimIndent() + ) + } + @Test fun `evaluate import`() { val result = evaluate("import \"pkl:base\"", "base")