languagetool-org/languagetool · error · RuntimeException

Your reference number ${refNumber} is bigger than the number

Error message

Your reference number ${refNumber} is bigger than the number of tokens: ${tokenPositions.size()}

What it means

In RuleFilterEvaluator.getResolvedArguments, an argument value like \N is a back-reference to the Nth pattern token. If N is larger than the number of collected token positions (or, in the following check, beyond the matched patternTokens), a RuntimeException is thrown. It means the filter references a token that does not exist in the pattern.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilterEvaluator.java:65

  }

  /**
   * Resolves the backref arguments, e.g. replaces {@code \1} by the value of the first token in the pattern.
   */
  public Map<String,String> getResolvedArguments(String filterArgs, AnalyzedTokenReadings[] patternTokens, int patternTokenPos, List<Integer> tokenPositions) {
    Map<String,String> result = new HashMap<>();
    String[] arguments = WHITESPACE.split(filterArgs);
    for (String arg : arguments) {
      int delimPos = arg.indexOf(':');
      if (delimPos == -1) {
        throw new RuntimeException("Invalid syntax for key/value, expected 'key:value', got: '" + arg + "'");
      }
      String key = arg.substring(0, delimPos);
      String val = arg.substring(delimPos + 1);
      if (val.startsWith("\\")) {
        int refNumber = Integer.parseInt(val.replace("\\", ""));
        if (refNumber > tokenPositions.size()) {
          throw new RuntimeException("Your reference number " + refNumber + " is bigger than the number of tokens: " + tokenPositions.size());
        }
        int correctedRef = getSkipCorrectedReference(tokenPositions, refNumber);
        if (correctedRef >= patternTokens.length) {
          throw new RuntimeException("Your reference number " + refNumber +
                  " is bigger than number of matching tokens: " + patternTokens.length);
        }
        if (result.containsKey(key)) {
          throw new RuntimeException("Duplicate key '" + key + "'");
        }
        result.put(key, patternTokens[correctedRef].getToken());
      } else {
        result.put(key, val);
      }
    }
    return result;
  }

  // when there's a 'skip', we need to adapt the reference number

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Lower the reference number so it points at an existing token: with N tokens, reference \1..\N (1-based).
  2. Recount the tokens in the <pattern> after recent edits and update every \N filter argument accordingly.
  3. Remember skip tokens and markers shift positions — verify against the actual matched token positions, not raw pattern text.
  4. Reproduce with a small test rule and print tokenPositions.size() to confirm how many positions the pattern actually yields.

Example fix

<!-- before: pattern has 2 tokens, filter references token 3 -->
<filter class="..." args="no:\3"/>
<!-- after -->
<filter class="..." args="no:\2"/>
Defensive patterns

Strategy: validation

Validate before calling

int maxRef = 0;
for (String arg : filterArgs.split("\\s+")) {
  String val = arg.substring(arg.indexOf(':') + 1);
  if (val.startsWith("\\")) {
    maxRef = Math.max(maxRef, Integer.parseInt(val.substring(1)));
  }
}
if (maxRef > tokenPositions.size()) {
  throw new IllegalArgumentException("Reference \\" + maxRef + " exceeds " + tokenPositions.size() + " tokens");
}

Try / catch

try {
  Map<String,String> resolved = evaluator.getResolvedArguments(filterArgs, patternTokens, pos, tokenPositions);
} catch (RuntimeException e) {
  if (e.getMessage().contains("is bigger than")) {
    throw new IllegalArgumentException("Back-reference out of range in: " + filterArgs, e);
  }
  throw e;
}

Prevention

When it happens

Trigger: A filter argument value starting with a backslash (e.g. \3) whose number exceeds tokenPositions.size() (the number of referenced token positions in the pattern), or whose skip-corrected index is >= patternTokens.length after skip handling.

Common situations: Rule pattern edited to have fewer tokens while the filter argument still references an old higher token index; numbering tokens from 0 instead of LanguageTool's 1-based convention; off-by-one after adding/removing a skip marker; copying a filter line between rules with different pattern lengths.

Related errors


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