languagetool-org/languagetool · error · IllegalArgumentException

AdvancedSynthesizerFilter: Index out of bounds in ${match.ge

Error message

AdvancedSynthesizerFilter: Index out of bounds in ${match.getRule().getFullId()}, value: ${postagFromStr}

What it means

AbstractAdvancedSynthesizerFilter.acceptRuleMatch() parses the rule's 'postagFrom' argument (absolute int or 'marker+N' offset) and validates it indexes into the matched pattern tokens (1..patternTokens.length). A value outside that range means the synthesizer rule misconfiguration references a token that doesn't exist in the match, so it throws.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/AbstractAdvancedSynthesizerFilter.java:74

    String lemmaSelect = getRequired("lemmaSelect", arguments);
    String postagFromStr = getRequired("postagFrom", arguments);
    String lemmaFromStr = getRequired("lemmaFrom", arguments);
    String newLemma = getOptional("newLemma", arguments, "");

    int postagFrom = 0;
    if (postagFromStr.startsWith("marker")) {
      while (postagFrom < patternTokens.length && patternTokens[postagFrom].getStartPos() < match.getFromPos()) {
        postagFrom++;
      }
      postagFrom++;
      if (postagFromStr.length()>6) {
        postagFrom += Integer.parseInt(postagFromStr.replace("marker", ""));
      }
    } else {
      postagFrom = Integer.parseInt(postagFromStr);
    }
    if (postagFrom < 1 || postagFrom > patternTokens.length) {
      throw new IllegalArgumentException("AdvancedSynthesizerFilter: Index out of bounds in "
          + match.getRule().getFullId() + ", value: " + postagFromStr);
    }
    int lemmaFrom = 0;
    if (lemmaFromStr.startsWith("marker")) {
      while (lemmaFrom < patternTokens.length && patternTokens[lemmaFrom].getStartPos() < match.getFromPos()) {
        lemmaFrom++;
      }
      lemmaFrom++;
      if (lemmaFromStr.length()>6) {
        lemmaFrom += Integer.parseInt(lemmaFromStr.replace("marker", ""));
      }
    } else {
      lemmaFrom = Integer.parseInt(lemmaFromStr);
    }
    if (lemmaFrom < 1 || lemmaFrom > patternTokens.length) {
      throw new IllegalArgumentException("AdvancedSynthesizerFilter: Index out of bounds in "
          + match.getRule().getFullId() + ", value: " + lemmaFromStr);
    }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Fix postag_from in the rule XML so it points to an existing token (1-based) within the matched pattern.
  2. Recount the rule pattern tokens after edits and update all *_from/*_to references.
  3. Check 'marker' arithmetic: the resolved marker+N must stay within patternTokens.length.
  4. Test the rule with LanguageTool's rule validation (e.g. via the rule editor or validateRuls tests) before deploying.

Example fix

// before (pattern has 2 tokens)
<filter class="...AdvancedSynthesizerFilter" args="postag_from:5 lemma_from:1"/>
// after
<filter class="...AdvancedSynthesizerFilter" args="postag_from:1 lemma_from:1"/>
Defensive patterns

Strategy: validation

Validate before calling

// at rule-authoring time
int postagFrom = Integer.parseInt(args.get("postag_from").replace("marker", ""));
if (postagFrom < 1 || postagFrom > patternTokens.length)
  throw new RuleFormatException("postag_from out of range");

Prevention

When it happens

Trigger: A rule using an AdvancedSynthesizerFilter supplies postagFrom (e.g. postag_from="5" or postag_from="marker:2" resolved value) that is <1 or greater than the number of tokens actually matched by the rule pattern.

Common situations: Editing a rule pattern to fewer tokens without updating postag_from; off-by-one confusion (positions are 1-based); using marker arithmetic that overshoots the token count.

Related errors


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