languagetool-org/languagetool · error · IllegalArgumentException

WordWithDeterminerFilter: Index out of bounds in " + match.g

Error message

WordWithDeterminerFilter: Index out of bounds in " + match.getRule().getFullId() + ", wordFrom: " + posWord

What it means

WordWithDeterminerFilter.acceptRuleMatch validates the 1-based 'wordFrom' filter argument against the matched pattern tokens and throws this IllegalArgumentException when posWord is < 1 or greater than patternTokens.length, meaning the rule references a word token position outside the pattern. (Note: the following posDeterminer check has a copy-paste bug — it prints posWord in its message.)

Source

Thrown at languagetool-language-modules/fr/src/main/java/org/languagetool/rules/fr/WordWithDeterminerFilter.java:64

  private static final List<String> exceptionsDeterminer =
    Arrays.asList("bels", "fols", "mols", "nouvels");

  private static final String categoryToCheck = "CAT_ELISION";
  private static final List<String> rulesToCheck = Arrays.asList("CET_CE", "CE_CET", "MA_VOYELLE", "MON_NFS", "VIEUX");

  @Override
  public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> arguments, int patternTokenPos,
                                   AnalyzedTokenReadings[] patternTokens, List<Integer> tokenPositions) throws IOException {
    JLanguageTool lt = Languages.getLanguageForShortCode("fr").createDefaultJLanguageTool();
    String wordFrom = getRequired("wordFrom", arguments);
    String determinerFrom = getRequired("determinerFrom", arguments);
    int posWord = 0;
    int posDeterminer = 0;
    if (wordFrom != null && determinerFrom != null) {
      posWord = Integer.parseInt(wordFrom);
      if (posWord < 1 || posWord > patternTokens.length) {
        throw new IllegalArgumentException("WordWithDeterminerFilter: Index out of bounds in "
            + match.getRule().getFullId() + ", wordFrom: " + posWord);
      }
      posDeterminer = Integer.parseInt(determinerFrom);
      if (posDeterminer < 1 || posDeterminer > patternTokens.length) {
        throw new IllegalArgumentException("WordWithDeterminerFilter: Index out of bounds in "
            + match.getRule().getFullId() + ", posDeterminer: " + posWord);
      }
    } else {
      throw new IllegalArgumentException("WordWithDeterminerFilter: undefined parameters wordFrom or determinerFrom in "
          + match.getRule().getFullId());
    }
    AnalyzedTokenReadings atrDeterminer = patternTokens[posDeterminer - 1];
    AnalyzedTokenReadings atrWord = patternTokens[posWord - 1];
    boolean isDeterminerCapitalized = StringTools.isCapitalizedWord(atrDeterminer.getToken());
    boolean isWordCapitalized = StringTools.isCapitalizedWord(atrWord.getToken());
    boolean isDeterminerAllupper = StringTools.isAllUppercase(atrDeterminer.getToken())
        && !atrDeterminer.getToken().equalsIgnoreCase("L'");
    boolean isWordAllupper = StringTools.isAllUppercase(atrWord.getToken());

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Set wordFrom to the correct 1-based token index within the pattern's length.
  2. Renumber wordFrom/determinerFrom together after every pattern change and add a rule test.
  3. Fix the adjacent bug so the posDeterminer error message prints posDeterminer, avoiding misleading diagnostics later.

Example fix

<!-- before: pattern has 3 tokens, arg points to 6 -->
<filter class="...WordWithDeterminerFilter" args="wordFrom:6 determinerFrom:1"/>
<!-- after -->
<filter class="...WordWithDeterminerFilter" args="wordFrom:2 determinerFrom:1"/>
Defensive patterns

Strategy: validation

Validate before calling

int wordFrom = Integer.parseInt(args.get("wordFrom"));
int patternLen = patternTokens.length;
if (wordFrom < 1 || wordFrom > patternLen) {
    throw new IllegalArgumentException("wordFrom must be 1.." + patternLen);
}

Try / catch

try { return filter.acceptRuleMatch(match, args, pos, tokens, tp); } catch (IllegalArgumentException e) { LOG.error("Rule " + match.getRule().getFullId() + ": " + e.getMessage()); return match; }

Prevention

When it happens

Trigger: A rule declares "wordFrom:N" where N is 0, negative, or larger than the number of tokens matched by the rule's <pattern>, evaluated when the rule match is post-processed by the filter.

Common situations: Renumbering mistakes after pattern edits; sharing args across rules with shorter patterns; confusion between the two positional args leading to swapped values.

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/bd10abf901cd98bb. Report an issue: GitHub.