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

  1. Diagnose the original IOException from the cause chain (resource path, permissions, disk).
  2. Validate and rebuild the language-module jar so dictionary binaries are intact.
  3. Return an empty suggestion list on synthesis failure so the grammar error is still reported.
  4. Add a startup synthesizer smoke test and alert if it fails.
  5. 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

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


AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06). Data as JSON: /api/errors/5d8af318812e60c8. Report an issue: GitHub.