languagetool-org/languagetool · error · RuntimeException

IOException while synthesizing suggestions (його/її -> нього

Error message

IOException while synthesizing suggestions (його/її -> нього/неї)

What it means

Another createRuleMatch() branch in TokenAgreementPrepNounRule handling «його»/«її» -> «него»/«неї» suggestions; after adding synthesized «їхній» forms and the replacement token, IOException from synthesize() is wrapped in RuntimeException. It indicates dictionary-synthesizer I/O failure, not a linguistic problem with the input text.

Source

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

      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 += ". Можливо, тут «о» — це вигук і потрібно кличний відмінок?";
          try {
            String newPostag = token.getPOSTag().replace("v_naz", "v_kly");
            String[] synthesized = synthesizer.synthesize(token, newPostag, false);
            for (String string : synthesized) {
              if( ! string.equals(token.getToken()) && ! suggestions.contains(string) ) {
                suggestions.add( string );
              }
            }
            break;
          } catch (IOException e) {
            throw new RuntimeException(e);
          }

View on GitHub (pinned to 2e990059ce)

Solutions

  1. Resolve the root IOException in the cause chain before anything else.
  2. Verify dictionary integrity in the deployed jar and redeploy a clean build if needed.
  3. Catch the RuntimeException at the API/service boundary and return the match without inflected suggestions.
  4. Add integration tests that run the rule over sample sentences to catch broken dictionaries in CI.
  5. Avoid post-build jar mutations (repackaging, filtering) that can corrupt .dict resources.

Example fix

// before
} catch (IOException e) {
  throw new RuntimeException(e);
}
// after
} catch (IOException e) {
  LOG.warn("pronoun suggestion synthesis failed", e);
  suggestions.add(repl); // still offer the direct replacement
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure dictionary loads before processing text
if (!isDictionaryHealthy()) {
  throw new IllegalStateException("Ukrainian synthesizer dictionary unhealthy; aborting check run");
}

Try / catch

try { matches = rule.match(tokens); }
catch (RuntimeException e) {
  if (e.getCause() instanceof IOException) { LOG.warn("pronoun-replacement synthesis failed", e); matches = Collections.emptyList(); }
  else throw e;
}

Prevention

When it happens

Trigger: Possessive pronoun agreement issue detected («його»/«її» with wrong-case noun); the rule synthesizes alternatives and the Morfologik dictionary read throws IOException.

Common situations: Corrupt or missing synthesizer dictionary in deployment; disk failures; jars damaged by build tooling (resource filtering of binary files).

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