languagetool-org/languagetool · error · RuntimeException
Rule group
Error message
Rule group
What it means
In pattern-rule XML, minPrevMatches may be set on a <rulegroup> or on individual <rule> elements, not both in a conflicting way. If a rule declares minPrevMatches while its rule group already set it to a value > 0, PatternRuleHandler.startElement throws this RuntimeException to prevent ambiguous inheritance.
Solutions
- Remove the minPrevMatches attribute from the inner <rule> and rely on the rulegroup value
- Or remove it from the <rulegroup> if the per-rule values are intended to differ
- Search the XML for rules inside groups that both define minPrevMatches and resolve the duplication
Example fix
// before <rulegroup id="G" minPrevMatches="2"> <rule id="R1" minPrevMatches="1">... // after <rulegroup id="G" minPrevMatches="2"> <rule id="R1">...
Defensive patterns
Strategy: validation
Validate before calling
if (ruleGroupMinPrevMatches > 0 && rule.hasAttribute("minPrevMatches")) {
throw new IllegalArgumentException("minPrevMatches set on both rulegroup and rule");
} Try / catch
try {
rules = handler.getRules(stream, filename);
} catch (RuntimeException e) {
if (e.getMessage().contains(MINPREVMATCHES)) {
log.error("Remove duplicate minPrevMatches in rule XML: {}", e.getMessage());
}
throw e;
} Prevention
- Define minPrevMatches at exactly one level (group or rule)
- Grep rule XML for nested minPrevMatches attributes in CI
- Document group-level inheritance when authoring rules
When it happens
Trigger: Parsing pattern rule XML where <rulegroup minPrevMatches="2"> contains a <rule minPrevMatches="..."> — i.e. the attribute is specified at both levels.
Common situations: Merging rule XML files or copying rules between groups, moving minPrevMatches to the group but leaving it on child rules (or vice versa), and bulk edits that duplicate the attribute.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- ApostropheTypeFilter: Index out of bounds in
- Translation language (
- AbstractAdvancedSynthesizerFilter only works with pattern…
- Cannot use --premiumAlways with non-premium version
- code is supposed to be a 2 (or rarely 3) character code…
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/2cd1183759efad05.
Report an issue: GitHub.
Appendix: source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java:179
inRegex = true;
regexMode = "exact".equals(attrs.getValue("type")) ? RegexpMode.EXACT : RegexpMode.SMART;
regexCaseSensitive = attrs.getValue(CASE_SENSITIVE) != null && YES.equals(attrs.getValue(CASE_SENSITIVE));
regexpMark = attrs.getValue(MARK) != null ? Integer.parseInt(attrs.getValue(MARK)) : 0;
break;
case RULE:
xmlLineNumber = pLocator.getLineNumber();
regex = new StringBuilder();
inRule = true;
shortMessage = new StringBuilder();
message = new StringBuilder();
suggestionsOutMsg = new StringBuilder();
url = new StringBuilder();
id = attrs.getValue(ID);
name = attrs.getValue(NAME);
String minPrevMatchesStr = attrs.getValue(MINPREVMATCHES);
if (minPrevMatchesStr != null) {
if (inRuleGroup && ruleGroupMinPrevMatches > 0) {
throw new RuntimeException("Rule group " + ruleGroupId + " has " + MINPREVMATCHES + "=" + ruleGroupMinPrevMatches
+ ", thus rule " + id + " cannot specify " + MINPREVMATCHES);
}
minPrevMatches = Integer.parseInt(minPrevMatchesStr);
} else {
minPrevMatches = ruleGroupMinPrevMatches;
}
String distanceTokensStr = attrs.getValue(DISTANCETOKENS);
if (distanceTokensStr != null) {
if (inRuleGroup && ruleGroupDistanceTokens > 0) {
throw new RuntimeException("Rule group " + ruleGroupId + " has " + DISTANCETOKENS + "=" + ruleGroupDistanceTokens
+ ", thus rule " + id + " cannot specify " + DISTANCETOKENS);
}
distanceTokens = Integer.parseInt(distanceTokensStr);
} else {
distanceTokens = ruleGroupDistanceTokens;
}
String premiumRule = attrs.getValue(PREMIUM);
//check if this rule is premiumView on GitHub (pinned to 2e990059ce)