languagetool-org/languagetool · error · RuntimeException
Error analyzing sentence: '${sentence}' with rule ${rule.get
Error message
Error analyzing sentence: '${sentence}' with rule ${rule.getFullId()} What it means
The catch-all branch of PatternRuleMatcher.match(): any non-IOException thrown while applying a pattern rule to a sentence is rethrown as RuntimeException('Error analyzing sentence: ...' with rule <fullId>). It names the failing rule so you can pinpoint the broken pattern definition. The cause is chained.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleMatcher.java:100
doMatch(sentence, tokens, (tokenPositions, firstMatchToken, lastMatchToken, firstMarkerMatchToken, lastMarkerMatchToken) -> {
RuleMatch ruleMatch = createRuleMatch(tokenPositions, tokens, firstMatchToken, lastMatchToken, firstMarkerMatchToken, lastMarkerMatchToken, sentence);
if (ruleMatch != null) {
ruleMatches.add(ruleMatch);
}
});
RuleMatchFilter maxFilter = new RuleWithMaxFilter();
List<RuleMatch> filteredMatches = maxFilter.filter(ruleMatches);
/*if (slowMatchThreshold != null) {
long runTime = System.currentTimeMillis() - startTime;
if (runTime > slowMatchThreshold) {
logger.warn("Slow match for rule " + rule.getFullId() + ": " + runTime + "ms, sentence len: " + sentence.getText().length() + " (threshold: " + slowMatchThreshold + "ms)");
}
}*/
return filteredMatches.toArray(RuleMatch.EMPTY_ARRAY);
} catch (IOException e) {
throw new IOException("Error analyzing sentence: '" + sentence + "'", e);
} catch (Exception e) {
throw new RuntimeException("Error analyzing sentence: '" + sentence + "' with rule " + rule.getFullId(), e);
} finally {
if (key != null) {
currentlyActiveRules.computeIfPresent(key, (k, v) -> v - 1 > 0 ? v - 1 : null);
}
}
}
@Override
protected boolean testAllReadings(AnalyzedTokenReadings[] tokens, PatternTokenMatcher matcher, PatternTokenMatcher prevElement, int tokenNo, int firstMatchToken, int prevSkipNext) throws IOException {
if (tokens[tokenNo].isImmunized()) return false;
return super.testAllReadings(tokens, matcher, prevElement, tokenNo, firstMatchToken, prevSkipNext);
}
@Nullable
private RuleMatch createRuleMatch(int[] tokenPositions,
AnalyzedTokenReadings[] tokens, int firstMatchToken,
int lastMatchToken, int firstMarkerMatchToken, int lastMarkerMatchToken,View on GitHub (pinned to 2e990059ce)
Solutions
- Read rule.getFullId() from the message and test that specific rule against the failing sentence.
- Inspect e.getCause() (e.g. PatternSyntaxException) and fix the rule's regex or token attributes.
- Validate the rule XML against LanguageTool's rule schema and simplify the pattern to isolate the offending token.
- Catch RuntimeException around getMatches per-rule and disable/report the broken rule at runtime.
Example fix
// before <token regexp="[a-z+"/> // after <token regexp="[a-z]+"/>
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-compile all regexes used in rules at load time for (String re : ruleRegexes) Pattern.compile(re); // throws PatternSyntaxException early
Try / catch
try {
matches = matcher.match(sentence...);
} catch (RuntimeException e) {
logger.error("Rule " + failingRuleId + " failed: " + e.getCause());
disabledRules.add(failingRuleId);
} Prevention
- Pre-compile every regex in custom rules at load time to fail fast.
- Validate rule XML structure against the LanguageTool rule schema.
- Isolate and unit-test each custom rule with representative sentences.
- After upgrades, re-run rule tests; attribute semantics can change.
When it happens
Trigger: getMatches -> match() when rule matching throws any RuntimeException/Error, e.g. IndexOutOfBounds/ClassCast from a malformed pattern token, regex PatternSyntaxException at match time, or NullPointerException in a tokenizer interacting with the rule.
Common situations: Hand-written rule XML with invalid regex or wrong attribute combinations that only fails when applied to a particular sentence; version upgrade changing PatternToken semantics; negative-scope or case-sensitivity attributes misused in custom rules.
Related errors
- Got " + matcher.groupCount() + " groups for regex '" + patte
- Got " + matcher.groupCount() + " groups for regex '" + patte
- suppressMisspelledMatch must be a valid regex
- suppressMisspelledSuggestions must be a valid regex
- WrongParameterNumberException
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/2467157238291cb5.
Report an issue: GitHub.