languagetool-org/languagetool · error · SAXException

Only backward references in match elements are possible, tri

Error message

Only backward references in match elements are possible, tried to specify token ${refNumber}
Line: ${pLocator.getLineNumber()}, column: ${pLocator.getColumnNumber()}.

What it means

XMLRuleHandler.checkRefNumber throws this SAXException when a <match no='N'> reference points to a token at or after the current pattern position. References in match elements may only be backward (to earlier tokens), because the token being matched cannot reference itself or a future token. The error names the offending token number and the XML location.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/XMLRuleHandler.java:433

      elements.append(refNumber);
    }
  }

  private void checkNumber(Attributes attrs) throws SAXException {
    if (StringTools.isEmpty(attrs.getValue("no"))) {
      throw new SAXException("References cannot be empty: " + "\n Line: "
          + pLocator.getLineNumber() + ", column: "
          + pLocator.getColumnNumber() + ".");
    } else if (Integer.parseInt(attrs.getValue("no")) < 1 && regex.length() == 0) {
      throw new SAXException("References must be larger than 0: "
          + attrs.getValue("no") + "\n Line: " + pLocator.getLineNumber()
          + ", column: " + pLocator.getColumnNumber() + ".");
    }
  }

  private void checkRefNumber(int refNumber) throws SAXException {
    if (refNumber > patternTokens.size()) {
      throw new SAXException("Only backward references in match elements are possible, tried to specify token "
          + refNumber + "\n" + "Line: " + pLocator.getLineNumber()
          + ", column: " + pLocator.getColumnNumber() + ".");
    }
  }

  protected void setExceptions(Attributes attrs) {
    inException = true;
    exceptions = new StringBuilder();
    resetException();

    exceptionStringNegation = YES.equals(attrs.getValue(NEGATE));
    exceptionValidNext = "next".equals(attrs.getValue(SCOPE));
    exceptionValidPrev = "previous".equals(attrs.getValue(SCOPE));
    exceptionStringInflected = YES.equals(attrs.getValue(INFLECTED));

    if (attrs.getValue(POSTAG) != null) {
      exceptionPosToken = StringInterner.intern(attrs.getValue(POSTAG));
      exceptionPosRegExp = YES.equals(attrs.getValue(POSTAG_REGEXP));

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Lower the 'no' value so it refers to an earlier token in the pattern
  2. Move the <match> element after the token it references, or restructure the rule
  3. Re-count token positions (1-based, counting only preceding pattern tokens) after editing the rule

Example fix

// before (first token cannot reference token 2)
<token>foo</token><match no="2"/>
// after
<token>foo</token><match no="1"/>
Defensive patterns

Strategy: validation

Validate before calling

// While building rules programmatically, track current token position
int currentPosition = /* index of token being defined */;
int refNumber = parseNo(matchElement);
if (refNumber > currentPosition) {
  throw new IllegalArgumentException("Forward reference no=" + refNumber + " at token " + currentPosition);
}

Type guard

boolean isBackwardReference(int refNumber, int tokensDefinedSoFar) {
  return refNumber >= 1 && refNumber <= tokensDefinedSoFar;
}

Try / catch

try {
  loader.getRules(is, filename);
} catch (SAXException e) {
  if (e.getMessage().startsWith("Only backward references")) {
    log.error("Renumber match references; they may only point to earlier tokens", e);
  } else throw e;
}

Prevention

When it happens

Trigger: Parsing rule XML where the 'no' attribute exceeds patternTokens.size() at parse time, e.g. <match no="2"/> placed as the first token, or referencing a token not yet defined in the pattern.

Common situations: Reordering tokens after writing matches and forgetting to renumber references; authors trying forward references; rules copied with offsets that no longer line up.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/e45e4dee847c2fa8. Report an issue: GitHub.