languagetool-org/languagetool · error · RuntimeException

AbstractAdvancedSynthesizerFilter only works with pattern ru

Error message

AbstractAdvancedSynthesizerFilter only works with pattern rules. ${rule.getFullId()} is not a pattern rule

What it means

AbstractAdvancedSynthesizerFilter.getLanguageFromRuleMatch() obtains the Language from the rule attached to a RuleMatch. It only knows how to do this when the rule is an AbstractPatternRule; for any other rule type it throws RuntimeException because there is no pattern to derive the language (and pattern-specific data) from.

Source

Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilter.java:145

    for (int tokenPosition : tokenPositions) {
      if (i++ >= refNumber) {
        break;
      }
      correctedRef += tokenPosition;
    }
    return correctedRef - 1;
  }

  public Language getLanguageFromRuleMatch(RuleMatch match) {
    Rule rule = match.getRule();
    if (this.language != null) {
      return language;
    }
    Language lang;
    if (rule instanceof AbstractPatternRule) {
      lang = ((PatternRule) match.getRule()).getLanguage();
    } else {
      throw new RuntimeException("AbstractAdvancedSynthesizerFilter only works with pattern rules. " + rule.getFullId() + " is not a pattern rule");
    }
    return lang;
  }

  public Synthesizer getSynthesizerFromRuleMatch(RuleMatch match) {
    return getLanguageFromRuleMatch(match).getSynthesizer();
  }

  public Tagger getTaggerFromRuleMatch(RuleMatch match) {
    return getLanguageFromRuleMatch(match).getTagger();
  }

  private Language language= null;

  public Language getLanguage() {
    return language;
  };

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Ensure the rule that raises the match extends AbstractPatternRule / is loaded from a pattern-rule XML
  2. In tests, build the RuleMatch from an actual PatternRule (with language set) instead of a generic Rule
  3. If you must support other rule types, override getLanguageFromRuleMatch or obtain the Language explicitly and use your own helper instead of the inherited one

Example fix

// before
RuleMatch match = new RuleMatch(new MyCustomRule(), ...);
Language lang = filter.getLanguageFromRuleMatch(match);
// after
PatternRule rule = new PatternRule("ID", language, tokens, "desc", "msg");
RuleMatch match = new RuleMatch(rule, ...);
Language lang = filter.getLanguageFromRuleMatch(match);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(match.getRule() instanceof AbstractPatternRule)) {
  throw new IllegalStateException("Filter requires a pattern rule, got " + match.getRule().getClass().getSimpleName());
}

Type guard

boolean isPatternRuleMatch(RuleMatch m) { return m != null && m.getRule() instanceof AbstractPatternRule; }

Try / catch

try {
  Synthesizer synth = getSynthesizerFromRuleMatch(match);
} catch (RuntimeException e) {
  if (e.getMessage().contains("only works with pattern rules")) { /* fall back to match.getSentence().getSnapshot or skip */ }
  else throw e;
}

Prevention

When it happens

Trigger: Calling getSynthesizerFromRuleMatch(match), getTaggerFromRuleMatch(match) or getLanguageFromRuleMatch(match) inside a RuleFilter whose rule match was produced by a non-pattern rule (e.g. a programmatically created Rule, a regex rule not extending AbstractPatternRule, or a synthetic test match).

Common situations: Writing a custom filter and testing it with a hand-constructed RuleMatch built around a plain Rule; attaching a filter to a rule type that is not an XML/pattern rule; LanguageTool version changes that changed the rule class hierarchy.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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