languagetool-org/languagetool · error · RuntimeException
IOException while synthesizing suggestions (numr-noun agreem
Error message
IOException while synthesizing suggestions (numr-noun agreement)
What it means
TokenAgreementNumrNounRule.match() wraps IOException from synthesizer.synthesize() in a RuntimeException while generating numeral-noun agreement suggestions. Like the other agreement rules, it treats synthesis failure as fatal for the match because suggestions are a core part of the reported error.
Source
Thrown at languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementNumrNounRule.java:597
for (String s : synthesized) {
if( numrCleanToken.equalsIgnoreCase("півтора")
&& nounToken.getLemma().equals("раз") && ! s.equals("раза") )
continue;
String suggestion = state.numrAnalyzedTokenReadings.getToken();
for(int j=state.numrPos+1; j<state.nounPos; j++ ) {
suggestion += " " + tokens[j].getToken(); // add middle adj
}
suggestion += " " + s;
if( ! suggestions.contains(suggestion) ) {
suggestions.add(suggestion);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
if( suggestions.size() > 0 ) {
potentialRuleMatch.setSuggestedReplacements(suggestions);
}
ruleMatches.add(potentialRuleMatch);
}
state.reset();
}
return toRuleMatchArray(ruleMatches);
}
View on GitHub (pinned to 2e990059ce)
Solutions
- Check the cause chain for the original IOException and fix the storage/resource issue.
- Validate the dictionary resources in the deployed artifact (checksums, jar listing).
- Redeploy a clean build of languagetool-language-modules/uk.
- Wrap rule execution so a synthesis failure degrades to a suggestion-less match instead of crashing the check run.
- Pin and verify artifact checksums in CI/CD to catch corrupted jars early.
Example fix
// before
} catch (IOException e) {
throw new RuntimeException(e);
}
// after
} catch (IOException e) {
LOG.warn("numr-noun suggestion synthesis failed", e);
suggestions.clear(); // report disagreement without inflected suggestions
} Defensive patterns
Strategy: try-catch
Validate before calling
// verify dictionary resource presence and readability
try (InputStream in = getClass().getResourceAsStream("/uk/ukrainian_synth.dict")) {
if (in == null || in.read() == -1) throw new IllegalStateException("Synth dictionary empty/missing");
} Try / catch
try { matches = rule.match(tokens); }
catch (RuntimeException e) {
if (e.getCause() instanceof IOException) { LOG.warn("numr-noun synthesis I/O failure", e); matches = Collections.emptyList(); }
else throw e;
} Prevention
- Validate artifact integrity (checksums) in the deploy pipeline
- Test agreement rules over sample sentences in CI
- Monitor RuntimeException-with-IOException-cause rates in production
- Ensure sufficient disk health where dictionaries are memory-mapped
When it happens
Trigger: Numeral-noun disagreement is detected and suggestion synthesis runs; the Morfologik synthesizer throws IOException while reading its dictionary (broken resource, stream closed, disk I/O error).
Common situations: Deployments with damaged language-module jars; dictionary files corrupted during transfer/copy; containers with truncated images; NFS/volume failures while the dictionary is being read.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- IOException while synthesizing suggestions (adj-noun agreeme
- IOException while synthesizing suggestions (verb-noun agreem
- throw new RuntimeException(e)
- Cannot synthesize <token><exception>
- IOException while synthesizing suggestions (prep-noun agreem
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/ad67e24beadae3da.
Report an issue: GitHub.