languagetool-org/languagetool · error · RuntimeException
IOException while synthesizing suggestions (verb-noun agreem
Error message
IOException while synthesizing suggestions (verb-noun agreement)
What it means
TokenAgreementVerbNounRule.getSuggestions() (used by the suggestions flow) rewrites the verb posTag and calls synthesizer.synthesize(analyzedToken, posTag, true) to produce agreeing verb forms; IOException is wrapped in RuntimeException. A failure means the Morfologik synthesizer could not read its dictionary while generating verb inflections.
Source
Thrown at languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementVerbNounRule.java:407
String requiredPostTagsRegEx = ":(" + String.join("|", cases) + ")";
Set<String> suggestions = new LinkedHashSet<>();
for (AnalyzedToken analyzedToken: tokenReadings.getReadings()) {
String oldPosTag = analyzedToken.getPOSTag();
if( oldPosTag == null || ! oldPosTag.contains(":v_") )
continue;
String posTag = oldPosTag.replaceFirst(":v_[a-z]+", requiredPostTagsRegEx);
try {
String[] synthesized = synthesizer.synthesize(analyzedToken, posTag, true);
suggestions.addAll( Arrays.asList(synthesized) );
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return new ArrayList<>(suggestions);
}
private String formatInflections(Set<String> cases) {
if( cases.isEmpty() )
return "неперех.";
return "вимагає: " + cases.stream()
.map(c -> PosTagHelper.VIDMINKY_I_MAP.get(c))
.collect(Collectors.joining(", "));
}
}
View on GitHub (pinned to 2e990059ce)
Solutions
- Diagnose the original IOException from the cause chain (resource path, permissions, disk).
- Validate and rebuild the language-module jar so dictionary binaries are intact.
- Return an empty suggestion list on synthesis failure so the grammar error is still reported.
- Add a startup synthesizer smoke test and alert if it fails.
- Keep binary dictionary resources out of any resource-filtering in the build.
Example fix
// before
String[] synthesized = synthesizer.synthesize(analyzedToken, posTag, true);
// after
String[] synthesized;
try {
synthesized = synthesizer.synthesize(analyzedToken, posTag, true);
} catch (IOException e) {
LOG.warn("verb synthesis failed; no suggestions", e);
synthesized = new String[0];
} Defensive patterns
Strategy: try-catch
Validate before calling
// startup check
try {
String[] t = synthesizer.synthesize(new AnalyzedToken("бачив", "verb:perf:past:m", "бачити"), "verb:perf:past:f", true);
if (t.length == 0) LOG.warn("Verb synthesis returned no forms");
} catch (IOException e) { throw new IllegalStateException("Verb synthesizer dictionary broken", e); } Try / catch
try { suggestions = rule.getSuggestions(tokens); }
catch (RuntimeException e) {
if (e.getCause() instanceof IOException) { LOG.warn("verb-noun synthesis failed", e); suggestions = Collections.emptyList(); }
else throw e;
} Prevention
- Smoke-test verb synthesis at startup
- Keep .dict resources out of build-time filtering
- Degrade to reporting the agreement error without inflected suggestions
- Pin artifact checksums and verify before deploy
When it happens
Trigger: Verb-noun disagreement detected in text; the rule builds inflected verb suggestions and the dictionary-backed synthesize() call throws IOException.
Common situations: Corrupted/missing Ukrainian dictionaries in the deployed jar; disk or volume I/O errors; jars damaged by shading/filtering; resource exhaustion during dictionary load.
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 (numr-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/5d8af318812e60c8.
Report an issue: GitHub.