{"record":{"id":"6d0dab31efb566ea","repo":"languagetool-org/languagetool","slug":"ioexception-while-initializing-spellers","errorCode":null,"errorMessage":"IOException while initializing spellers","messagePattern":"IOException while initializing spellers","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/MorfologikUkrainianSpellerRule.java","lineNumber":182,"sourceCode":"\n  @Override\n  protected List<SuggestedReplacement> filterSuggestions(List<SuggestedReplacement> suggestions) {\n    suggestions = super.filterSuggestions(suggestions);\n    // do not suggest \"кіно прокат, вело- прогулянка...\":\n    suggestions.removeIf(item -> item.getReplacement().contains(\" \") &&\n        DO_NOT_SUGGEST_SPACED_PATTERN.matcher(item.getReplacement()).matches() ||\n        item.getReplacement().contains(\"- \"));\n    return suggestions;\n  }\n\n  // workaround to allow other rules generate spelling suggestions without invoking match()\n  MorfologikMultiSpeller getSpeller1() {\n    if( speller1 == null ) {\n      try {\n        // we can't call initSpellers() as it's private so we're calling method we can\n        isMisspelled(\"1\");\n      } catch (IOException e) {\n        throw new RuntimeException(e);\n      }\n    }\n    return speller1;\n  }\n\n  @Override\n  protected boolean isLatinScript() {\n    return false;\n  }\n}\n","sourceCodeStart":164,"sourceCodeEnd":193,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/MorfologikUkrainianSpellerRule.java#L164-L193","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the Morfologik dictionary resources exist in the languagetool-language-modules/uk jar (unzip -l and look for *.dict).","Rebuild/reinstall the language module so resources are packaged correctly.","Run with the original (non-shaded) LanguageTool jars to avoid resource filtering stripping binary files.","Inspect e.getCause() for the true failure (file corruption, permissions, classpath) and fix that.","Pre-initialize spellers at startup in a guarded block so failures surface with clear diagnostics before serving traffic."],"exampleFix":"// before\nMorfologikMultiSpeller speller = rule.getSpeller1(); // throws RuntimeException on bad resource\n// after\ntry {\n  MorfologikMultiSpeller speller = rule.getSpeller1();\n} catch (RuntimeException e) {\n  LOG.error(\"Ukrainian speller init failed; check uk dictionary resources on classpath\", e);\n}","handlingStrategy":"try-catch","validationCode":"try (InputStream in = getClass().getResourceAsStream(\"/uk/ukrainian.dict\")) {\n  if (in == null) throw new IllegalStateException(\"Ukrainian speller dictionary missing from classpath\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  MorfologikMultiSpeller speller = rule.getSpeller1();\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof IOException) { LOG.error(\"Speller dictionary unreadable; disable spell check for uk\", e); }\n  else throw e;\n}","preventionTips":["Verify dictionary resources are packaged in the jar before deployment (unzip -l)","Warm up speller initialization at startup, not on first user request","Avoid shaded/filtered repackaging that strips or corrupts binary .dict files","Keep artifact checksums pinned in CI to catch corrupted builds"],"tags":["io","speller","classpath","lazy-initialization"],"backgroundTag":"file-read-failed","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}