languagetool-org/languagetool · error · IllegalArgumentException

ConfusionCheckFilter: Index out of bounds in " + match.getRu

Error message

ConfusionCheckFilter: Index out of bounds in " + match.getRule().getFullId() + ", PronounFrom: " + posPronoun

What it means

InterrogativeVerbFilter.acceptRuleMatch reads a 1-based 'PronounFrom' token position from the rule's filter arguments and validates it against the pattern's token count. This IllegalArgumentException is thrown when the parsed value is < 1 or greater than the number of pattern tokens, i.e. the rule XML points at a token that does not exist in the matched sentence's token window.

Source

Thrown at languagetool-language-modules/fr/src/main/java/org/languagetool/rules/fr/InterrogativeVerbFilter.java:68

    morfologikRule = French.getInstance().getDefaultSpellingRule();
  }

  @Override
  public RuleMatch acceptRuleMatch(RuleMatch match, Map<String, String> arguments, int patternTokenPos,
                                   AnalyzedTokenReadings[] patternTokens, List<Integer> tokenPositions) throws IOException {
    /*if (match.getSentence().getText().contains("Peut je")) {
      int ii=0;
      ii++;
    }*/
    List<String> replacements = new ArrayList<>();
    String pronounFrom = getRequired("PronounFrom", arguments);
    String verbFrom = getRequired("VerbFrom", arguments);
    String desiredPostag = null;
    List<String> extraSuggestions = new ArrayList<>();
    if (pronounFrom != null && verbFrom != null) {
      int posPronoun = Integer.parseInt(pronounFrom);
      if (posPronoun < 1 || posPronoun > patternTokens.length) {
        throw new IllegalArgumentException("ConfusionCheckFilter: Index out of bounds in " + match.getRule().getFullId()
            + ", PronounFrom: " + posPronoun);
      }
      int posVerb = Integer.parseInt(verbFrom);
      if (posVerb < 1 || posVerb > patternTokens.length) {
        throw new IllegalArgumentException(
            "ConfusionCheckFilter: Index out of bounds in " + match.getRule().getFullId() + ", VerbFrom: " + posVerb);
      }

      //AnalyzedTokenReadings atrVerb = patternTokens[posVerb - 1];
      AnalyzedTokenReadings atrPronoun = patternTokens[posPronoun - 1];
      
      // vous
      if (atrPronoun.matchesPosTagRegex("R pers obj 2 p")) {
        desiredPostag = "V.* (imp) [23] [sp]|V .*(ind|cond).* 2 p";
      }
      // nous
      else if (atrPronoun.matchesPosTagRegex("R pers obj 1 p")) {
        desiredPostag = "V.* (imp) .*|V .*(ind|cond).* 1 p";

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Recount the tokens in the rule's <pattern> and set PronounFrom to the correct 1-based index (1..patternTokens.length).
  2. Renumber all positional args (PronounFrom, VerbFrom) after any pattern edit.
  3. Add a startup-time test (LanguageTool rule tests) covering the pattern so out-of-range positions fail in CI, not at runtime.

Example fix

<!-- before: pattern has 3 tokens, arg points to 5 -->
<filter class="...InterrogativeVerbFilter" args="PronounFrom:5 VerbFrom:2"/>
<!-- after -->
<filter class="...InterrogativeVerbFilter" args="PronounFrom:3 VerbFrom:2"/>
Defensive patterns

Strategy: validation

Validate before calling

int pronounFrom = Integer.parseInt(args.get("PronounFrom"));
int patternLen = patternTokens.length;
if (pronounFrom < 1 || pronounFrom > patternLen) {
    throw new IllegalArgumentException("PronounFrom 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 args like "PronounFrom:5" but the pattern it attaches to matches only, say, 3 tokens; or the argument is 0/negative/miscounted because tokens were added/removed from the pattern during a rule edit.

Common situations: After editing a rule's token list, positional arguments were not renumbered; off-by-one mistakes (1-based indexing misunderstood); reusable rules whose patterns have different lengths sharing the same filter args.

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