Is your feature request related to a problem? Please describe.
Yes. When eXist throws an error but fails to provide a location where the error was thrown, debugging is very difficult.
Describe the solution you'd like
I'd like to find a way to ensure all XPathExceptions (if not all error types? I don't know them all?) can include a location.
For example, the following query:
xquery version "3.1";
"" cast as xs:dateTime
... should include the location (line 3, column _) in the error message, but instead all we get is a description, without any location information:
err:FORG0001 illegal lexical form for date-time-like value ''
Similarly:
(map { "id": 1 })[map:size(.) eq 1]
throws the following location-less error description:
err:XPTY0004 checking function parameter 1 in call map:size(self::node()): cannot convert map(*)('') to a node set
The lack of location makes fixing the error very difficult.
Describe alternatives you've considered
I tried adding "this" as the first argument to one case of XPathException, https://github.com/eXist-db/exist/blob/984b64183619b6887a409a0d315e6d262fb31ffe/exist-core/src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java#L89, but this error was thrown during compilation:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project exist-core: Compilation failure
[ERROR] /Users/joe/workspace/exist/exist-core/src/main/java/org/exist/xquery/value/AbstractDateTimeValue.java:[89,19] no suitable constructor found for XPathException(org.exist.xquery.value.AbstractDateTimeValue,org.exist.xquery.ErrorCodes.ErrorCode,java.lang.String,java.lang.IllegalArgumentException)
[ERROR] constructor org.exist.xquery.XPathException.XPathException(int,int,org.exist.xquery.ErrorCodes.ErrorCode,java.lang.String) is not applicable
[ERROR] (argument mismatch; org.exist.xquery.value.AbstractDateTimeValue cannot be converted to int)
[ERROR] constructor org.exist.xquery.XPathException.XPathException(org.exist.xquery.Expression,org.exist.xquery.ErrorCodes.ErrorCode,java.lang.String,org.exist.xquery.value.Sequence) is not applicable
[ERROR] (argument mismatch; org.exist.xquery.value.AbstractDateTimeValue cannot be converted to org.exist.xquery.Expression)
[ERROR] constructor org.exist.xquery.XPathException.XPathException(org.exist.xquery.ErrorCodes.ErrorCode,java.lang.String,org.exist.xquery.value.Sequence,java.lang.Throwable) is not applicable
[ERROR] (argument mismatch; org.exist.xquery.value.AbstractDateTimeValue cannot be converted to org.exist.xquery.ErrorCodes.ErrorCode)
[ERROR] constructor org.exist.xquery.XPathException.XPathException(int,int,java.lang.String,java.lang.Throwable) is not applicable
[ERROR] (argument mismatch; org.exist.xquery.value.AbstractDateTimeValue cannot be converted to int)
Additional context
eXist 5.2.0, Java 8, current macOS, DMG
Perhaps we could catalog best practices for error throwing, so we can consult them when we find errors being thrown without location information:
Another variation of the problem: a query that triggers an error with location -1:-1 instead of the actual line and column where the error occurs:
xquery version "3.1";
(1, 2) => replace(".", "")
Error:
err:XPTY0004 Invalid cardinality for parameter $vp0. Expected zero or one, got 2 [source: xquery version "3.1"; (1, 2) => replace(".", "")] In function: replace(xs:string?, xs:string, xs:string)
[-1:-1:String]
(Also, $vp0?)
I think it is a great idea to collect all those errors. In many cases - like above - they are thrown by org.exist.xquery.value objects, which do not have access to the expression they were called from. The calling expression should catch those errors, fill in the missing information and rethrow. This is happening in many cases already, but not all.
@wolfgangmm using the calling expression might not work, as it could have a different line number.
I have also seen many cases where eXist reports the wrong line number or even module
@adamretter We might as well catalog those too here in this master issue - i.e., the cases where eXist reports the wrong line number or even module.
@joewiz the second code example is actually a bug in the xquery implementation of exist (see https://github.com/eXist-db/exist/issues/3244) -> I just saw you reported that bug already :)
Most helpful comment
I think it is a great idea to collect all those errors. In many cases - like above - they are thrown by
org.exist.xquery.valueobjects, which do not have access to the expression they were called from. The calling expression should catch those errors, fill in the missing information and rethrow. This is happening in many cases already, but not all.