languagetool-org/languagetool · error · SAXException

References must be larger than 0: ${attrs.getValue("no")} L

Error message

References must be larger than 0: ${attrs.getValue("no")}
 Line: ${pLocator.getLineNumber()}, column: ${pLocator.getColumnNumber()}.

What it means

XMLRuleHandler.checkNumber throws this SAXException when a reference element's 'no' attribute parses to a value less than 1 (e.g. 0 or negative) and no regex attribute is present. Token references are 1-based backward references into the pattern, so 0 or negative values are meaningless. The exception includes the offending value plus line/column of the XML.

Source

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

      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) {
    inException = true;
    exceptions = new StringBuilder();
    resetException();

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Change the 'no' value to 1 or higher (1-based, referring to a previous token)
  2. If you intended an offset via regex, supply the regex attribute instead of a bare number
  3. Run LanguageTool's rule tests to validate all reference numbers after editing

Example fix

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

Strategy: validation

Validate before calling

int no = Integer.parseInt(attrs.getValue("no"));
if (no < 1) throw new IllegalArgumentException("'no' must be >= 1, got " + no);

Type guard

boolean isPositiveRef(String no) {
  try { return Integer.parseInt(no) >= 1; } catch (NumberFormatException e) { return false; }
}

Try / catch

try {
  loader.getRules(is, filename);
} catch (SAXException e) {
  if (e.getMessage().startsWith("References must be larger than 0")) {
    log.error("Token references are 1-based; fix the 'no' value", e);
  } else throw e;
}

Prevention

When it happens

Trigger: A <match no="0"/> (or negative) in rule XML is parsed and regex.length() == 0, so the value cannot be interpreted as a regex-alternative and checkNumber rejects it.

Common situations: Authors thinking references are 0-based like array indices; generated XML starting counters at 0; hand-written rules converting from other grammar formats.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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