languagetool-org/languagetool · error · SAXException

References cannot be empty: Line: ${pLocator.getLineNumber

Error message

References cannot be empty: 
 Line: ${pLocator.getLineNumber()}, column: ${pLocator.getColumnNumber()}.

What it means

XMLRuleHandler.checkNumber throws this SAXException while parsing rule XML when a <match> element (or similar reference element) has an empty 'no' attribute. The 'no' attribute must contain the number of the pattern token to reference back to. The parser fails at the reported line/column so the author can locate the malformed element.

Source

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

    } else if (inSuggestion) {
      suggestionMatchesOutMsg.add(mWorker);
      // add incorrect XML character for simplicity
      suggestionsOutMsg.append("\u0001\\");
      suggestionsOutMsg.append(attrs.getValue("no"));
      checkNumber(attrs);
    } else if (inToken && attrs.getValue("no") != null) {
      int refNumber = Integer.parseInt(attrs.getValue("no"));
      checkRefNumber(refNumber);
      mWorker.setTokenRef(refNumber);
      tokenReference = mWorker;
      elements.append('\\');
      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) {

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Set the 'no' attribute to a positive integer referencing a preceding token, e.g. <match no="1"/>
  2. Validate the XML against the rules DTD/XSD before loading
  3. Lint rule XML files in CI to catch empty required attributes

Example fix

// before
<match no=""/>
// after
<match no="1" postag="NN"/>
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate rule XML for empty required 'no' attributes
Document doc = parseXml(ruleFile);
XPath xpath = XPathFactory.newInstance().newXPath();
NodeList bad = (NodeList) xpath.evaluate("//*[@no='']", doc, XPathConstants.NODESET);
if (bad.getLength() > 0) throw new SAXException("Empty 'no' attribute in " + ruleFile);

Type guard

boolean hasValidNoAttr(Attributes attrs) {
  String v = attrs.getValue("no");
  return v != null && !v.trim().isEmpty() && v.chars().allMatch(Character::isDigit);
}

Try / catch

try {
  loader.getRules(is, filename);
} catch (SAXException e) {
  if (e.getMessage().contains("References cannot be empty")) {
    log.error("Set the 'no' attribute at " + e.getMessage(), e);
  } else throw e;
}

Prevention

When it happens

Trigger: A <match no=""/> or <match/> element without a 'no' attribute is parsed by the rule XML SAX handler; StringTools.isEmpty(attrs.getValue("no")) is true and checkNumber throws.

Common situations: Hand-editing rule XML and deleting the attribute value, templating tools emitting empty attributes, XML generated with missing required fields, migrating rules between formats.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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