Bug #2710

Internal Saxon error: local variable encountered whose binding has been deleted

Added by Gunther Rademacher over 4 years ago. Updated about 3 years ago.

XQuery conformance
Start date:
Due date:
% Done:


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


This XQuery, when compiled with Saxon 9.7, throws an IllegalStateException:

for $j in (text{'Az'}, text{'Bx'}, text{'Cy'}) 
order by $j/substring(., $j/string-length(.)) 
return $j

The stacktrace is attached. Some similar construct was found in generated XQuery code while upgrading to Saxaon-EE 9.7.

syserr.log (2.78 KB) syserr.log output on System.err; stack trace Gunther Rademacher, 2016-04-14 12:48


#1 Updated by Michael Kay over 4 years ago

  • Category set to XQuery conformance
  • Status changed from New to In Progress
  • Assignee set to Michael Kay

Problem reproduced.

Added to QT3 test suite as prod-OrderByClause/OrderBy67

#2 Updated by Michael Kay over 4 years ago

The problem occurs because a SortKeyDefinition (which is a pseudo-Expression node on the expression tree) does not hold its operands (that is, its children on the Expression tree) as Operand objects, but instead constructs them on demand when the operands() method is called. This has the consequence that when an operand is rewritten as part of an optimization rewrite, the rewritten expression does not find its way back into the SortKeyDefinition object. In this case the rewritten expression declares a generated local variable, and we end up with a reference to the variable in the expression tree, but not the LetExpression that binds the variable.

A quick check shows some other expressions that are constructing Operand objects dynamically during the operands() call, and which could therefore suffer from the same problem: WhichOf, MergeInstr, CompareToIntegerConstant, LocalParam, NumberInstruction, SortKeyDefinitionList, and various Pattern subclasses (where it may be safe).

#3 Updated by Michael Kay over 4 years ago

I have changed SortKeyDefinition on the 9.7 branch to use Operands properly and it fixes the problem. Regression tested by running the QT3 prod-OrderByClause and XSLT3 sort test sets. Patch copied to 9.8 branch, and committed on both.

Leaving open because other expression classes need the same treatment.

#4 Updated by Michael Kay over 4 years ago

  • Status changed from In Progress to Resolved
  • Applies to branch 9.8 added
  • Fix Committed on Branch 9.7, 9.8 added

I have reviewed the other cases where we are creating Operand objects dynamically and have decided to make no changes unless we can show there is a problem. In all these cases there is a reasonably good reason why the class is written the way it is, and it seems to me that making changes without having a test case that demonstrates there is a problem is excessively risky. Therefore closing the issue as resolved.

#5 Updated by Alexander Henket over 4 years ago

I encountered this same thing running a rather complex stylesheet in eXist-db 2.2 (saxonhe- Running the same thing outside of eXist-db 2.2 using Saxon-EE gave me no trouble.

Since the original ticket was about xquery, I just wanted to make sure this or is not the same thing that has been fixed.

Original code:

    <xsl:variable name="classifications" select="document('DECOR.xsd')/*/xs:simpleType[@name='TemplateTypes']/*/xs:enumeration" as="element()+"/>
    <xsl:for-each-group select="$allTemplates/*/ref/template" group-by="if (classification/@type) then (classification/@type)[1] else ('notype')">
        <xsl:sort select="count($classifications[@value=current-grouping-key()]/preceding-sibling::*)"/>

I've rewritten it like below to circumvent this:

    <xsl:variable name="classifications" select="document('DECOR.xsd')/*/xs:simpleType[@name='TemplateTypes']/*/xs:enumeration" as="element()+"/>
    <xsl:for-each-group select="$allTemplates/*/ref/template" group-by="
        (if (classification/@type) then (
        ) else (
        )) + 1">
        <xsl:sort select="current-grouping-key()"/>
        <xsl:variable name="classification" select="$classifications[position()=current-grouping-key()]/@value"/>

#6 Updated by Michael Kay over 4 years ago

Alexander, this error message is caused by a tree corruption during optimization, and there can be a wide variety of underlying causes with the same symptom: the fact that it's the same message doesn't mean it's the same bug. I'm afraid it's probably not worth our while investigating a problem that occurs on 9.4 that can't be reproduced on a more recent release.

#7 Updated by Michael Kay over 4 years ago

I had to make some further changes to SortKeyDefinition to make comparison of sort keys in xsl:merge work again. Patched on 9.7 and 9.8 branches.

#8 Updated by O'Neil Delpratt over 4 years 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.

#9 Updated by O'Neil Delpratt over 4 years ago

  • Sprint/Milestone set to

#10 Updated by O'Neil Delpratt about 3 years ago

  • Applies to branch trunk added
  • Applies to branch deleted (9.8)

#11 Updated by O'Neil Delpratt about 3 years ago

  • Fix Committed on Branch trunk added
  • Fix Committed on Branch deleted (9.8)

Please register to edit this issue

Also available in: Atom PDF