languagetool-org/languagetool · error · RuntimeException
No alternative found for:
Error message
No alternative found for:
What it means
getAlternativeTerm scans the confusion set for the entry whose text differs from the current token to return as the alternative suggestion. This RuntimeException is thrown when no such entry exists, meaning every entry equals the token — an inconsistency given the size-2 precondition.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/ngrams/ConfusionProbabilityRule.java:309
return grams;
}
@Nullable
private ConfusionString getBetterAlternativeOrNull(GoogleToken token, List<GoogleToken> tokens, List<ConfusionString> confusionSet, long factor) {
if (confusionSet.size() != 2) {
throw new RuntimeException("Confusion set must be of size 2: " + confusionSet);
}
ConfusionString other = getAlternativeTerm(confusionSet, token);
return getBetterAlternativeOrNull(token, tokens, other, factor);
}
private ConfusionString getAlternativeTerm(List<ConfusionString> confusionSet, GoogleToken token) {
for (ConfusionString s : confusionSet) {
if (!s.getString().equals(token.token)) {
return s;
}
}
throw new RuntimeException("No alternative found for: " + token);
}
private ConfusionString getConfusionString(List<ConfusionString> confusionSet, GoogleToken token) {
for (ConfusionString s : confusionSet) {
if (s.getString().equalsIgnoreCase(token.token)) {
return s;
}
}
throw new RuntimeException("Not found in set '" + confusionSet + "': " + token);
}
private ConfusionString getBetterAlternativeOrNull(GoogleToken token, List<GoogleToken> tokens, ConfusionString otherWord, long factor) {
String word = token.token;
double p1;
double p2;
if (grams == 3) {
p1 = LanguageModelUtils.get3gramProbabilityFor(language, lm, token, tokens, word);
p2 = LanguageModelUtils.get3gramProbabilityFor(language, lm, token, tokens, otherWord.getString());View on GitHub (pinned to 2e990059ce)
Solutions
- Check the token and confusion set contents reported in the message.
- Fix the confusion data so the set holds two distinct words.
- Verify token normalization/case handling doesn't collapse both entries to the same string.
Example fix
// before (confusion data) their their // after (confusion data) their there
Defensive patterns
Strategy: validation
Validate before calling
// ensure the confusion set has two distinct entries before lookup
if (set.stream().map(ConfusionString::getString).distinct().count() != 2)
throw new IllegalStateException("Confusion set entries must be distinct: " + set); Try / catch
try { rule.match(...); } catch (RuntimeException e) { if (e.getMessage().startsWith("No alternative found")) log.error("Duplicated confusion data: " + e.getMessage()); throw e; } Prevention
- Avoid duplicate lines in confusion data files
- Sanity-check data with a distinct-entry assertion
- Keep token normalization consistent with data entries
When it happens
Trigger: A confusion set whose entries all equal the matched token (e.g. duplicated entries), so the loop finds no differing string and falls through to the throw.
Common situations: Confusion data containing the same word twice instead of two distinct words; token normalization differences that make both entries compare equal to the token.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Confusion set must be of size 2:
- grams must be between 1 and 5:
- Not found in set '
- Directory must contain at least '1grams', '2grams', and '3gr
- Expected at least '1grams', '2grams', and '3grams' sub direc
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/3ba67793b60b8ffa.
Report an issue: GitHub.