Bug #5102

System.ArgumentNullException from message listener (unknown location URI?)

Added by Emanuel Wlaschitz about 1 month ago. Updated about 1 month ago.

Start date:
Due date:
% Done:


Estimated time:
Legacy ID:
Applies to branch:
Fix Committed on Branch:
Fixed in Maintenance Release:


We're currently in the process of updating to Saxon-HE 10.6N and one of our stylesheets started to blow up for no apparent reason. Deep down we see this one:

  Message=Value cannot be null.
Parameter name: uriString
   at System.Uri..ctor(String uriString)

  This exception was originally thrown at this call stack:

...which is at:

 	System.dll!System.Uri.Uri(string uriString)	Unknown
 	saxon-he-api-10.6.dll!Saxon.Api.MessageListenerProxy2.message(net.sf.saxon.s9api.XdmNode xn, net.sf.saxon.s9api.QName qn, bool b, javax.xml.transform.SourceLocator sl)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.MessageListener2Proxy.write( value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.SequenceWriter.append( item, net.sf.saxon.s9api.Location locationId, int copyNamespaces)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.MessageListener2Proxy.append( value, net.sf.saxon.s9api.Location value, int value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.SequenceWriter.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.TreeReceiver.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.ProxyReceiver.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.event.ComplexContentOutputter.endDocument()	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.Message.processLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.Block.processLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContext context)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.trans.Mode.applyTemplates(net.sf.saxon.expr.instruct.ParameterSet parameters, net.sf.saxon.expr.instruct.ParameterSet tunnelParameters, separator, net.sf.saxon.event.Outputter output, net.sf.saxon.expr.XPathContextMajor context, net.sf.saxon.s9api.Location locationId)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.trans.XsltController.applyTemplates( source, net.sf.saxon.event.Receiver out)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(javax.xml.transform.Source value, net.sf.saxon.event.Receiver value)	Unknown
 	saxon-he-10.6.dll!net.sf.saxon.s9api.XsltTransformer.transform()	Unknown
 	saxon-he-api-10.6.dll!Saxon.Api.XsltTransformer.Run(Saxon.Api.XmlDestination destination)	Unknown

...and is followed up by this when ignoring exceptions that are caught internally:

  Message=Internal error evaluating template rule  in module file:///D:/_dev/SaxonMLP2NullPointer/bin/Debug/SaxonMLP2NullPointer.exe
   at net.sf.saxon.expr.instruct.TemplateRule.applyLeavingTail(Outputter output, XPathContext context)
   at net.sf.saxon.trans.Mode.applyTemplates(ParameterSet parameters, ParameterSet tunnelParameters, NodeInfo separator, Outputter output, XPathContextMajor context, Location locationId)
   at net.sf.saxon.trans.XsltController.applyTemplates(Sequence source, Receiver out)
   at net.sf.saxon.s9api.AbstractXsltTransformer.applyTemplatesToSource(Source , Receiver )
   at net.sf.saxon.s9api.XsltTransformer.transform()
   at Saxon.Api.XsltTransformer.Run(XmlDestination destination)
   at SaxonMLP2NullPointer.Program.Main(String[] args) in D:\_dev\SaxonMLP2NullPointer\Program.cs:line 39

Inner Exception 1:

It appears that in those cases, SourceLocator sl inside MessagListenerProxy2.message is net.sf.saxon.expr.parser.Loc@1029822 { columnNumber: -1, lineNumber: -1, systemId: null } and fails when attempting to set location.BaseUri = new Uri(sl.getSystemId()); due to sl.getSystemId() returning null.

I managed to create a stripped down example that still causes the issue, and it appears to be related to having both a custom MessageListener2 on the XsltTransformer, as well as writing a <xsl:message> that contains either <xsl:value-of/> or <xsl:sequence/> to produce the message itself from a non-xs:string source (that is: no select attribute, any expression that is not of type xs:string or uses any function to produce a xs:string; including a call to concat()).

Here's the (minimalistic) source:

internal class Program
    private static void Main(string[] args)
        var xslt = XDocument.Parse(@"
        <stylesheet xmlns='' version='3.0'>
            <template match='/'>
                <!-- this message causes an error when MessageListener2 is used -->
                <message><value-of select='local-name()'/></message>
                <result xmlns=''/>
        var input = xslt; // does not matter for this test.
        var output = new XDocument();

        var processor = new Processor();
        using (var xsltReader = xslt.CreateReader())
        using (var inputReader = input.CreateReader())
        using (var outputWriter = output.CreateWriter())
            var compiler = processor.NewXsltCompiler();
            compiler.BaseUri = new Uri(typeof(Program).Assembly.Location);
            var xsltExecutable = compiler.Compile(xsltReader);

            var transformer = xsltExecutable.Load();

            var builder = processor.NewDocumentBuilder();
            transformer.InitialContextNode = builder.Build(inputReader);
            // comment this out to prevent the issue
            transformer.MessageListener2 = new TestMessageListener();

            var destination = new TextWriterDestination(outputWriter) { CloseAfterUse = true };
    private sealed class TestMessageListener : IMessageListener2
        public void Message(XdmNode content, QName errorCode, bool terminate, IXmlLocation location) { }

The code will work when:

  1. transformer.MessageListener2 is not set by the code (or transformer.MessageListener if the errorCode parameter is not neede by the listener)
  2. The contents of <message> is plain text (such as <message>test</message>)
  3. The contents of <message> is a string variable (such as <variable name="message" select="'test'"/><message><value-of select="$message"/></message>)

The code will not work when:

  1. The contents of <message> is produced by a function call (such as <message><value-of select="concat('Message here: ', $message)"/></message>)
  2. The contents of <message> is not of type xs:string (such as <variable name="message" select="42"/><message><value-of select="$message"/></message>)
  3. The contents of <message> use the concatenation operator (such as <message><value-of select="Message here: " || $message"/></message> - which might be the same as the first case though)

For obvious reasons, we can't simply not add the MessageListener2 because we want to capture <xsl:message> including the errorCode. And the same thing happens if we revert back to MessageListener, except that it happens in MessageListenerProxy instead of MessageListenerProxy2 in that case.

This is using the currently most recent NuGet package with version 10.6.0 on .NET Framework 4.8


#1 Updated by Emanuel Wlaschitz about 1 month ago

Oops, my bad, I started typing the title, then got side-tracked and forgot about it. Should probably something like "NullPointerException in MessageListenerProxy2 for non-string xsl:message content" or so.

#2 Updated by Michael Kay about 1 month ago

  • Subject changed from Null to System.ArgumentNullException from message listener (unknown location URI?)

Thanks for reporting it, we'll take a look.

Missing location URIs are a constant source of trouble.

Please register to edit this issue

Also available in: Atom PDF