languagetool-org/languagetool · error · RuntimeException

IOException while initializing spellers

Error message

IOException while initializing spellers

What it means

MorfologikUkrainianSpellerRule.getSpeller1() lazily initializes the Morfologik spellers by calling isMisspelled("1") (which triggers initSpellers()); if that initialization throws an IOException it is wrapped in a RuntimeException. The speller dictionaries are compiled binary resources loaded from the classpath, so an IOException here means the dictionary data could not be read.

Solutions

  1. Verify the Morfologik dictionary resources exist in the languagetool-language-modules/uk jar (unzip -l and look for *.dict).
  2. Rebuild/reinstall the language module so resources are packaged correctly.
  3. Run with the original (non-shaded) LanguageTool jars to avoid resource filtering stripping binary files.
  4. Inspect e.getCause() for the true failure (file corruption, permissions, classpath) and fix that.
  5. Pre-initialize spellers at startup in a guarded block so failures surface with clear diagnostics before serving traffic.

Example fix

// before
MorfologikMultiSpeller speller = rule.getSpeller1(); // throws RuntimeException on bad resource
// after
try {
  MorfologikMultiSpeller speller = rule.getSpeller1();
} catch (RuntimeException e) {
  LOG.error("Ukrainian speller init failed; check uk dictionary resources on classpath", e);
}
Defensive patterns

Strategy: try-catch

Validate before calling

try (InputStream in = getClass().getResourceAsStream("/uk/ukrainian.dict")) {
  if (in == null) throw new IllegalStateException("Ukrainian speller dictionary missing from classpath");
}

Try / catch

try {
  MorfologikMultiSpeller speller = rule.getSpeller1();
} catch (RuntimeException e) {
  if (e.getCause() instanceof IOException) { LOG.error("Speller dictionary unreadable; disable spell check for uk", e); }
  else throw e;
}

Prevention

When it happens

Trigger: First call to getSpeller1() (directly or via the first spell-check) when the Morfologik .dict/.info resources cannot be opened from the classpath, e.g. corrupted jar, missing resource, or I/O failure reading the binary dictionary.

Common situations: Incomplete/dependency-broken build where Ukrainian spelling resources weren't packaged; running from a shaded jar that excluded binary resources; running inside a container with a broken or partially extracted jar; classpath isolation (app servers) hiding resources.

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

Appendix: source

Thrown at languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/MorfologikUkrainianSpellerRule.java:182

  @Override
  protected List<SuggestedReplacement> filterSuggestions(List<SuggestedReplacement> suggestions) {
    suggestions = super.filterSuggestions(suggestions);
    // do not suggest "кіно прокат, вело- прогулянка...":
    suggestions.removeIf(item -> item.getReplacement().contains(" ") &&
        DO_NOT_SUGGEST_SPACED_PATTERN.matcher(item.getReplacement()).matches() ||
        item.getReplacement().contains("- "));
    return suggestions;
  }

  // workaround to allow other rules generate spelling suggestions without invoking match()
  MorfologikMultiSpeller getSpeller1() {
    if( speller1 == null ) {
      try {
        // we can't call initSpellers() as it's private so we're calling method we can
        isMisspelled("1");
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }
    return speller1;
  }

  @Override
  protected boolean isLatinScript() {
    return false;
  }
}

View on GitHub (pinned to 2e990059ce)