Report the reason, the expression and the location of runtime render errors - #89
Open
AlexKalnitskiy wants to merge 3 commits into
Open
Report the reason, the expression and the location of runtime render errors#89AlexKalnitskiy wants to merge 3 commits into
AlexKalnitskiy wants to merge 3 commits into
Conversation
…etic operation Previously any arithmetic result which could not be converted to a template value was reported as a bare "Arithmetic operation result could not be evaluated" with no location at all, which made it impossible to tell which template expression had failed and why. Arithmetic expressions now keep the place they were parsed from, and the failure is thrown as ArithmeticOperationException, which carries: - Reason: DivisionByZero, NotANumber or ResultOutOfRange; - Expression: the failed expression as it is written in the template; - Location: inherited from UnrenderableTemplateModelException, now filled in. The same parts are put into Exception.Data under the QuokkaExceptionData keys, so that the calling code can build its own (e.g. localized) message without parsing the message text. UnrenderableTemplateModelException also puts its location into Exception.Data, so every runtime error is uniform in that regard. The resulting message reads: Arithmetic operation result could not be evaluated: division by zero in "cart.total / cart.itemCount" at 12:34 ArithmeticOperationException derives from UnrenderableTemplateModelException, so the existing catch blocks keep working. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Arithmetic errors were given the reason, the expression and the location in the previous commit; the remaining runtime render errors — a null value usage, a missing variable value and a failed function call — still reported neither the expression nor the location in the message text. All runtime render errors now share one message shape, built in one place (the UnrenderableTemplateModelException base): <error text>[: <details>][ in "<expression>"][ at <line:column>] - An attempt to use a null value in "cell.Value" at 4:14 - Value for variable not found in "a" at 1:41 - Function invocation resulted in error: Argument must be positive in "picky()" at 1:3 The stable error texts are exposed as constants, the expression is exposed as a typed property on the base exception, and Exception.Data is filled uniformly with QuokkaExceptionData.ErrorText and Expression in addition to the location entries, so the calling code can build its own (e.g. localized) message for any runtime error without parsing the message text. Function calls now keep their source text the same way arithmetic expressions do, so the failed call is reported as written in the template, e.g. "max(a, b)" rather than just the function name. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- A runtime error raised while evaluating a function argument now propagates as itself: arguments are evaluated before the try block, so an arithmetic failure inside an argument is no longer re-wrapped into a generic "Function invocation resulted in error" losing its reason and expression. - The captured expression source text is capped at 100 characters (an ellipsis is appended), so unbounded template expressions can't bloat messages, Data entries or the compiled template. - Expression is normalized to null when blank, so Message and Data[Quokka.Expression] can't disagree about whether an expression exists. - Location.Column is documented as 0-based, matching the values the engine has always produced (ANTLR CharPositionInLine). - The DivisionByZero doc no longer claims infinity is only reachable by dividing by zero (a chain of multiplications can overflow to infinity), and the QuokkaExceptionData doc scopes the Data contract to runtime render errors. - Version bumped to 8.4.0: new public API and changed error messages. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Previously runtime render errors were hard to trace back to the template: an arithmetic failure was reported as a bare
Arithmetic operation result could not be evaluatedwith no location at all, and the other runtime errors (a null value usage, a missing variable value, a failed function call) named the variable or the function but never the location.Every runtime render error now reports the expression as it is written in the template and the location, in one message shape built in one place (the
UnrenderableTemplateModelExceptionbase):Arithmetic failures are thrown as
ArithmeticOperationExceptionwith a typedReason:DivisionByZero,NotANumberorResultOutOfRange. The other error texts are exposed as constants on the base exception, and the failed expression is a typedExpressionproperty on it.The same parts are put into
Exception.Dataunder theQuokkaExceptionDatakeys (ErrorText,Reason,Expression,Location,Line,Column), so that the calling code can build its own (e.g. localized) message for any runtime error without parsing the message text.Details:
max(a / b, 1)keeps its reason and expression.Data) and is capped at 100 characters.Location.Columnis documented as 0-based, matching the values the engine has always produced.ArithmeticOperationExceptionderives fromUnrenderableTemplateModelExceptionand the other errors keep their exception type, so the existing catch blocks keep working.Tests: 494/494 green on net8.0 and net9.0 (14 new). Two existing tests were adjusted: the division-by-zero one now allows a derived exception type, and the null-cell-value one asserts the new message wording.
🤖 Generated with Claude Code