Bug #4251

java.lang.NullPointerException in Saxon-EE but not Saxon-PE

Added by Tony Graham 9 months ago. Updated 7 months ago.

XPath conformance
Start date:
Due date:
% Done:


Legacy ID:
Applies to branch:
9.9, trunk
Fix Committed on Branch:
9.9, trunk
Fixed in Maintenance Release:


I am getting a java.lang.NullPointerException only in Saxon-EE.

I will add a sample as soon as I can. I am posting the stack trace now in the hope that you have an 'Aha!' moment sooner than I can whittle everything down to a manageable size.

        at net.sf.saxon.expr.VariableReference.computeCardinality(
        at net.sf.saxon.expr.Expression.computeStaticProperties(
        at net.sf.saxon.expr.Expression.getDependencies(
        at net.sf.saxon.expr.Expression.computeDependencies(
        at net.sf.saxon.expr.Expression.computeStaticProperties(
        at net.sf.saxon.expr.Expression.getCardinality(
        at net.sf.saxon.expr.parser.TypeChecker.staticTypeCheck(
        at net.sf.saxon.expr.GeneralComparison.typeCheck(

To this untrained eye, this looks similar to #2567

Unfortunately, the first and last stylesheet references in the stack trace are:

Caused by: java.lang.RuntimeException: Internal error evaluating template rule  at line 98 in module file:/P:/tgraham/pubsrc/xsl/xxxxx2pdf/generateBookmarks.xsl

which is this template:

  <xsl:template mode="make-bookmark-label" match="xhtml:header" as="xs:string?">
    <xsl:param name="doDebug" as="xs:boolean" tunnel="yes" select="false()"/>
    <xsl:variable name="content">
      <xsl:apply-templates mode="#current">
        <xsl:with-param name="doDebug" as="xs:boolean" tunnel="yes" select="$doDebug"/>

  	<xsl:variable name="base-text">
      <xsl:value-of select="$content"/>
    <xsl:sequence select="normalize-space($base-text)"/>

so I'm not expecting much joy until you can see a sample.

stacktrace.txt (47.5 KB) Tony Graham, 2019-07-12 18:56 stacktrace.txt


#1 Updated by Michael Kay 9 months ago

Thanks for reporting it. I'm afraid with internal errors like this, we usually need to be able to reproduce them in order to make any progress, so a complete stylesheet would be appreciated. It's worth seeing if the problem still occurs if JIT compilation of template rules is disabled (-opt:-j).

The stack trace gives a rough indication of what's going on: a filter expression such as $x[ppp = $y] has been optimised into an "indexed filter expression" and this is being typechecked, which is failing because there's a variable reference whose properties have not been fully initialized. But we need to find out why, and that can only be done by reproducing it. The fragment of the stylesheet you've shown us doesn't seem relevant because there's no filter expression involved.

#2 Updated by Michael Kay 9 months ago

In fact it's on a slightly unusual path where the IndexedFilterExpression optimization is being reversed based on new information: the variable to which the predicate applies has been inlined, which makes it possible to make a more intelligent decision about whether indexing is appropriate. But it will still be hard to solve without a repro.

#3 Updated by Michael Kay 9 months ago

I think I can see what's wrong with the code, and I might be prepared to hazard an untested patch, but it would be much better to have a repro that we can test it on. It's not easy to construct a test case that will take this path. I could try running the test suite to see whether any existing tests take this path but I suspect the answer will be that there aren't any, otherwise we would have seen the failure.

#4 Updated by Tony Graham 9 months ago

I gave up hope on your 'Aha!' moment when I saw how dull the most significant template from the stack trace really was. I included it anyway, otherwise you would have asked for it.

Innumerable stack traces later...

<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="">

<?xml version="1.0" encoding="UTF-8"?>


    <xsl:variable name="class-value" select="string(@class)"/>
    <xsl:variable name="subtitle-text" as="xs:string?"
      select="normalize-space(following-sibling::*[local:hasDataTypeToken(., 'subtitle')])"

    <xsl:variable name="new-class"
      select="if ($subtitle-text ne '')
              then string-join(($class-value, 'has-subtitle'), ' ')
              else $class-value"
      <xsl:if test="$new-class ne ''">
        <xsl:attribute name="class" select="$new-class"/>

  <!-- Return true if the specified element has any of the specified
       tokens in its @data-type value.
  <xsl:function name="local:hasDataTypeToken" as="xs:boolean">
    <xsl:param name="context" as="element()"/>
    <xsl:param name="tokens" as="xs:string*"/>
    <!-- <xsl:message select="exists($context/@data-type)" /> -->
    <xsl:variable name="result" as="xs:boolean"
      select="tokenize($context/@data-type, ' ') = ($tokens)"
    <xsl:sequence select="$result"/>


#5 Updated by Michael Kay 9 months ago

Thanks. Problem now reproduced.

What's happening is that it does an indexing optimization for the many-to-many "=" comparison

tokenize($context/@data-type, ' ') = ($tokens)

and then reverses this optimization after it inlines the function and discovers that the value of $tokens is actually a singleton.

Nothing wrong with that in principle, but it turns out to be a path that hasn't been suitably exercised and the data on the reverse optimization isn't properly initialized.

#6 Updated by Michael Kay 9 months ago

  • Category set to XPath conformance
  • Assignee set to Michael Kay
  • Priority changed from Low to Normal
  • Applies to branch 9.9, trunk added
  • Fix Committed on Branch 9.9, trunk added

#7 Updated by Michael Kay 9 months ago

  • Status changed from New to Resolved

#8 Updated by O'Neil Delpratt 7 months ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release added

Bug fix applied in the Saxon maintenance release.

Please register to edit this issue

Also available in: Atom PDF