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

  1. Check the cause chain for the original IOException and fix the storage/resource issue.
  2. Validate the dictionary resources in the deployed artifact (checksums, jar listing).
  3. Redeploy a clean build of languagetool-language-modules/uk.
  4. Wrap rule execution so a synthesis failure degrades to a suggestion-less match instead of crashing the check run.
  5. 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

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


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