Bug #4886


Error "Cannot copy a variable reference whose binding is unknown" when using inline variables in specific situation

Added by Maarten Kroon over 1 year ago. Updated over 1 year ago.

Start date:
Due date:
% Done:


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



In some of my stylesheet transformations a Java exception is thrown with the message "Cannot copy a variable reference whose binding is unknown". I tried to create a simple example in which the error can be reproduced. The error seems to occur when:

  • The variable reference is an inline variable (expand-text="yes")
  • The template in which the variable is used has both a name and match attribute.
  • The template is in an included/imported stylesheet and the variable is declared in the including/importing stylesheet.

The transformation can be executed using the command:

java -jar saxon-he-10.3.jar -s:source.xml -xsl:including.xsl

All files are attached

Regards, Maarten


including.xsl (297 Bytes) including.xsl Maarten Kroon, 2021-01-29 16:24
included.xsl (334 Bytes) included.xsl Maarten Kroon, 2021-01-29 16:24
source.xml (47 Bytes) source.xml Maarten Kroon, 2021-01-29 16:24
stacktrace.txt (1.42 KB) stacktrace.txt Maarten Kroon, 2021-01-29 16:24
Actions #1

Updated by Michael Kay over 1 year ago

  • Category set to Internals
  • Status changed from New to In Progress
  • Assignee set to Michael Kay
  • Priority changed from Low to Normal
  • Applies to branch 10, trunk added

Thanks for reporting it.

To reproduce this, I had to run with Saxon-HE, or with Saxon-EE with the -opt:0 flag to disable optimisations.

Actions #2

Updated by Michael Kay over 1 year ago

In fact -opt:-j is sufficient to trigger it. It's happening during compilation of the template rule, which is being copied because it has both a match and a name attribute, so one copy is optimised for invocation-by-name and the other for invocation-by-pattern. The opt:-j option suppresses just-in-time template rule compilation, i.e. it forces eager (early) compilation.

Actions #3

Updated by Michael Kay over 1 year ago

Well, I can see clearly what's happening, but it requires some thinking to see how to fix it. Thanks for putting together such a simple repro: when presented like this it's hard to believe that the failure isn't happening all the time, but as you say in the report there are a number of conditions that have to occur together to trigger the fault.

When the template rule is changed to

<xsl:template name="unused" match="/*"><a a="{$test}"/></xsl:template>

Then it all works time, so I'm studying that case to remind myself how it's supposed to work. In this case, while we are parsing the XPath expression (using a fast-path XPath parser, as it happens, that recognises simple expressions like $test without doing a full parse), we call env.bindVariable(name), and this locates the global xsl:variable and registers a (forwards) reference to it. Later, we process all components in order, including the xsl:template, and call fixupReferences() recursively to find all outgoing component references in that template, which should find the variable reference and update it to point to the compiled global variable.

With the attribute value template StyleElement.fixupReferences() processes the global variable and finds one reference to the variable. With the text value template, it finds that the reference list is empty.

It seems that the fixupReferences() call is happening before the expression in the TVT has even been parsed.

This is because expressions occurring in attributes are parsed during the first pass over the stylesheet (the prepareAttributes pass), whereas expressions in TVTs are only parsed during the second pass (the validateSubtree pass).

We can't simply move all the processing of TVTs into the first pass, because the processing first parses the XPath expressions and then does type-checking, and we aren't ready to do type checking yet in the first pass. So we need to split it into two.

Doing so fixes this test case. Now need to run regression tests.

Actions #4

Updated by Michael Kay over 1 year ago

I'm seeing 3 failures from 11623 tests in the XSLT 3.0 test suite:

  • accumulator-088
  • forwards-011
  • transform-008

These are all tests for recent bugs that are still open, and the changed code only affects XSLT, so I think we'll deem this OK.

Actions #5

Updated by Michael Kay over 1 year ago

  • Status changed from In Progress to Resolved
  • Fix Committed on Branch 10, trunk added

Added test case cvt-048 to the XSLT4 test suite.

Switched to development branch and the test unexpectedly passed. The original repro still fails. I forgot (a) that the template needs to have a match pattern as well as a name, and (b) that we need to run with opt:-j

Actions #6

Updated by O'Neil Delpratt over 1 year ago

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

Bug fix applied to Saxon 10.5 maintenance release.

Please register to edit this issue

Also available in: Atom PDF