languagetool-org/languagetool · error · RuntimeException
Unexpected reference to capturing group in rule with id %s.
Error message
Unexpected reference to capturing group in rule with id %s.
What it means
Raised while a regex-based XML rule matches: the rule's message or suggestion text references a capturing group (a back-reference like \1) that the rule's regular expression never captured. The faulty input is the rule's <message>/<suggestion> markup referencing a group number that does not exist in the pattern.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/RegexPatternRule.java:124
String processedSuggestionsOutMsg = processMessage(patternMatcher, suggestionsOutMsg, backReferencesInSuggestionsOutMsg,
suggestionsInSuggestionsOutMsg, getSuggestionMatchesOutMsg());
boolean startsWithUpperCase = patternMatcher.start() == 0 && Character.isUpperCase(text.charAt(patternMatcher.start()));
RuleMatch ruleMatch = new RuleMatch(this, sentenceObj, markStart, markEnd, patternMatcher.start(), patternMatcher.end(),
processedMessage, shortMessage, startsWithUpperCase, false, processedSuggestionsOutMsg, true);
if (regexFilter != null) {
RegexRuleFilterEvaluator ruleFilterEvaluator = new RegexRuleFilterEvaluator(regexFilter);
RuleMatch filteredMatch = ruleFilterEvaluator.runFilter(getFilterArguments(), ruleMatch, sentenceObj, patternMatcher);
if (filteredMatch != null) {
matches.add(ruleMatch);
}
} else {
matches.add(ruleMatch);
}
startPos = patternMatcher.end();
} catch (IndexOutOfBoundsException e){
throw new RuntimeException(String.format("Unexpected reference to capturing group in rule with id %s.", this.getFullId()), e);
} catch (Exception e) {
throw new RuntimeException(String.format("Unexpected exception when processing regexp in rule with id %s.", this.getFullId()), e);
}
}
return matches.toArray(RuleMatch.EMPTY_ARRAY);
}
@NotNull
private List<Pair<Integer, Integer>> getClausePositionsInMessage(Pattern pattern, String message) {
Matcher matcher = pattern.matcher(message);
List<Pair<Integer, Integer>> clausePositionsInMessage = new ArrayList<>();
while (matcher.find()) {
clausePositionsInMessage.add(Pair.of(matcher.start(), matcher.end()));
}
return clausePositionsInMessage;
}
private String processMessage(Matcher matcher, String message, List<Pair<Integer, Integer>> backReferences,View on GitHub (pinned to 2e990059ce)
Solutions
- Add the missing capturing parentheses to the rule's regular expression so the referenced group exists
- Correct the back-reference number in the message so it points to an existing group
- Refer to the rule id quoted in the exception to locate and fix the offending grammar.xml entry
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/RegexPatternRule.java:124 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/67d968bbef2e644d.
Report an issue: GitHub.