languagetool-org/languagetool · error · RuntimeException
Confusion set must be of size 2:
Error message
Confusion set must be of size 2:
What it means
getBetterAlternativeOrNull expects each confusion set to contain exactly two candidate words (the word and its alternative). This RuntimeException is an internal invariant check that fires when a confusion set loaded from the confusion data has a size other than 2.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/ngrams/ConfusionProbabilityRule.java:297
public void setConfusionPair(ConfusionPair pair) {
wordToPairs.clear();
for (ConfusionString word : pair.getTerms()) {
wordToPairs.put(word.getString(), Collections.singletonList(pair));
}
}
/**
* Returns the ngram level used, typically 3.
* @since 3.1
*/
public int getNGrams() {
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;View on GitHub (pinned to 2e990059ce)
Solutions
- Inspect the confusion set printed in the message and find its source entry in the language's confusion data.
- Ensure each confusion set has exactly two entries.
- Re-generate or re-download the confusion data for the language if it was modified.
Example fix
// before (confusion data: 1 entry) their // after (confusion data: 2 entries) their there
Defensive patterns
Strategy: validation
Validate before calling
// validate confusion data sets are pairs before running rules
confusionSets.forEach((word, set) -> {
if (set.size() != 2) throw new IllegalStateException("Confusion set must be size 2: " + word + " -> " + set);
}); Try / catch
try { rule.match(...); } catch (RuntimeException e) { if (e.getMessage().startsWith("Confusion set must be of size 2")) { log.error("Corrupt confusion data: " + e.getMessage()); } throw e; } Prevention
- Validate confusion data files in CI
- Re-download data after upstream updates rather than hand-editing
- Keep pairs of distinct words in every set
When it happens
Trigger: A confusion set loaded from the language's confusion data resource contains one or more than two entries, then the rule tries to compute the better alternative during rule matching.
Common situations: Malformed or hand-edited confusion-set data files; a data update changed the set format; case-related duplicates collapsed into one entry.
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
- No alternative found for:
- 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/0d8f93504be35187.
Report an issue: GitHub.