{"record":{"id":"9d66777a4e1a392b","repo":"languagetool-org/languagetool","slug":"abstractadvancedsynthesizerfilter-only-works-with","errorCode":null,"errorMessage":"AbstractAdvancedSynthesizerFilter only works with pattern rules. ${rule.getFullId()} is not a pattern rule","messagePattern":"AbstractAdvancedSynthesizerFilter only works with pattern rules\\. (.+?) is not a pattern rule","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilter.java","lineNumber":145,"sourceCode":"    for (int tokenPosition : tokenPositions) {\n      if (i++ >= refNumber) {\n        break;\n      }\n      correctedRef += tokenPosition;\n    }\n    return correctedRef - 1;\n  }\n\n  public Language getLanguageFromRuleMatch(RuleMatch match) {\n    Rule rule = match.getRule();\n    if (this.language != null) {\n      return language;\n    }\n    Language lang;\n    if (rule instanceof AbstractPatternRule) {\n      lang = ((PatternRule) match.getRule()).getLanguage();\n    } else {\n      throw new RuntimeException(\"AbstractAdvancedSynthesizerFilter only works with pattern rules. \" + rule.getFullId() + \" is not a pattern rule\");\n    }\n    return lang;\n  }\n\n  public Synthesizer getSynthesizerFromRuleMatch(RuleMatch match) {\n    return getLanguageFromRuleMatch(match).getSynthesizer();\n  }\n\n  public Tagger getTaggerFromRuleMatch(RuleMatch match) {\n    return getLanguageFromRuleMatch(match).getTagger();\n  }\n\n  private Language language= null;\n\n  public Language getLanguage() {\n    return language;\n  };\n","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/RuleFilter.java#L127-L163","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Ensure the rule that raises the match extends AbstractPatternRule / is loaded from a pattern-rule XML","In tests, build the RuleMatch from an actual PatternRule (with language set) instead of a generic Rule","If you must support other rule types, override getLanguageFromRuleMatch or obtain the Language explicitly and use your own helper instead of the inherited one"],"exampleFix":"// before\nRuleMatch match = new RuleMatch(new MyCustomRule(), ...);\nLanguage lang = filter.getLanguageFromRuleMatch(match);\n// after\nPatternRule rule = new PatternRule(\"ID\", language, tokens, \"desc\", \"msg\");\nRuleMatch match = new RuleMatch(rule, ...);\nLanguage lang = filter.getLanguageFromRuleMatch(match);","handlingStrategy":"type-guard","validationCode":"if (!(match.getRule() instanceof AbstractPatternRule)) {\n  throw new IllegalStateException(\"Filter requires a pattern rule, got \" + match.getRule().getClass().getSimpleName());\n}","typeGuard":"boolean isPatternRuleMatch(RuleMatch m) { return m != null && m.getRule() instanceof AbstractPatternRule; }","tryCatchPattern":"try {\n  Synthesizer synth = getSynthesizerFromRuleMatch(match);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"only works with pattern rules\")) { /* fall back to match.getSentence().getSnapshot or skip */ }\n  else throw e;\n}","preventionTips":["Only attach AbstractAdvancedSynthesizerFilter subclasses to rules loaded from pattern-rule XML","In tests, construct RuleMatch from a real PatternRule created with the target Language","Do not reuse the filter with programmatically built plain Rule objects"],"tags":["java","languagetool","rule-filter","pattern-rule"],"backgroundTag":"unsupported-operation","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}