languagetool-org/languagetool · error · RuntimeException

IOException while synthesizing suggestions (їх -> їхній)

Error message

IOException while synthesizing suggestions (їх -> їхній)

What it means

Same createRuleMatch() flow in TokenAgreementPrepNounRule, but for the special-case suggestion «їх» -> «їхній»: synthesize() is called with a synthetic AnalyzedToken("їхній", ...) and IOException is wrapped in RuntimeException. The failure means the dictionary synthesizer could not be read while building this possessive-pronoun suggestion.

Source

Thrown at languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementPrepNounRule.java:550

        state.prepTokenReadings.getToken(), String.join(", ", reqVidminkyNames), String.join(", ", foundVidminkyNames));

    if( state.ziZnaRemoved ) {
      msg += ". Але з.в. вимагається у випадках порівнянн предметів.";
    }

    if( state.posTagsToFind.contains("v_rod")
        && tokens[i].getToken().matches(".*[ую]")
        && PosTagHelper.hasPosTag(tokenReadings.getReadings(), Pattern.compile("noun.*?:m:v_dav.*")) ) {
      msg += CaseGovernmentHelper.USED_U_INSTEAD_OF_A_MSG;
    }
    else if( tokenString.equals("їх") && requiredPostTagsRegEx != null ) {
      msg += ". Можливо, тут потрібно присвійний займенник «їхній» або нормативна форма р.в. «них»?";
      try {
        String newYihPostag = "adj:p" + requiredPostTagsRegEx + ".*";
        String[] synthesized = synthesizer.synthesize(new AnalyzedToken("їхній", "adj:m:v_naz.*:pron:pos", "їхній"), newYihPostag, true);
        suggestions.addAll( Arrays.asList(synthesized) );
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    else if( (tokenString.equals("його") || tokenString.equals("її")) && requiredPostTagsRegEx != null ) {
      String repl = tokenString.equals("його") ? "нього" : "неї";
      msg += ". Можливо, тут потрібно присвійний займенник «" + repl + "»?";
      try {
        String newYihPostag = "adj:p" + requiredPostTagsRegEx + ".*";
        String[] synthesized = synthesizer.synthesize(new AnalyzedToken("їхній", "adj:m:v_naz.*:pron:pos", "їхній"), newYihPostag, true);
        suggestions.addAll( Arrays.asList(synthesized) );
        suggestions.add(repl);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    else if( state.prepTokenReadings.getCleanToken().equalsIgnoreCase("о") ) {
      for(AnalyzedToken token: tokenReadings.getReadings()) {
        if( PosTagHelper.hasPosTag(token, NOUN_ANIM_V_NAZ_PATTERN) ) {
          msg += ". Можливо, тут «о» — це вигук і потрібно кличний відмінок?";

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Fix the underlying IOException found in the cause chain (resource, disk, permissions).
  2. Rebuild/verify the uk dictionary resources in the artifact.
  3. Degrade gracefully: keep the message but skip synthesized suggestions when synthesis fails.
  4. Run a startup smoke test of the synthesizer to catch dictionary problems before serving requests.
  5. Monitor for repeated RuntimeExceptions with this stack to detect environment-level dictionary corruption.

Example fix

// before
String[] synthesized = synthesizer.synthesize(new AnalyzedToken("їхній", "adj:m:v_naz.*:pron:pos", "їхній"), newYihPostag, true);
// after
String[] synthesized;
try {
  synthesized = synthesizer.synthesize(new AnalyzedToken("їхній", "adj:m:v_naz.*:pron:pos", "їхній"), newYihPostag, true);
} catch (IOException e) {
  LOG.warn("synthesis for їхній failed", e);
  synthesized = new String[0];
}
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  synthesizer.synthesize(new AnalyzedToken("їхній", "adj:m:v_naz.*:pron:pos", "їхній"), "adj:p:v_naz", true);
} catch (IOException e) { throw new IllegalStateException("Cannot synthesize їхній forms", e); }

Try / catch

try { matchResult = rule.match(tokens); }
catch (RuntimeException e) {
  if (e.getCause() instanceof IOException) { LOG.warn("їхній synthesis failed; keep message, drop suggestions", e); }
  else throw e;
}

Prevention

When it happens

Trigger: Text contains «їх» where an adjectival possessive or normative genitive is expected; the rule synthesizes forms of «їхній» and the synthesizer throws IOException.

Common situations: Same root causes as other synthesis failures: damaged Morfologik dictionaries, storage I/O errors, broken deployment artifacts.

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/fb76ecca94cc7463. Report an issue: GitHub.