{"record":{"id":"84dbf1cda6f58d09","repo":"languagetool-org/languagetool","slug":"ioexception-while-synthesizing-suggestions-prep-n","errorCode":null,"errorMessage":"IOException while synthesizing suggestions (prep-noun agreement)","messagePattern":"IOException while synthesizing suggestions \\(prep-noun agreement\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementPrepNounRule.java","lineNumber":500,"sourceCode":"      \n      String requiredPostTagsRegExToApply = requiredPostTagsRegEx;\n\n      Matcher matcher = REQ_ANIM_INANIM_PATTERN.matcher(oldPosTag);\n      if( matcher.find() ) {\n        requiredPostTagsRegExToApply += matcher.group(0);\n      }\n      else {\n        requiredPostTagsRegExToApply += \"(?:\" + reqAnimInanimRegex + \")?\";\n      }\n\n      String posTag = oldPosTag.replaceFirst(\":v_[a-z]+\", requiredPostTagsRegExToApply);\n\n      try {\n        String[] synthesized = synthesizer.synthesize(analyzedToken, posTag, true);\n\n        suggestions.addAll( Arrays.asList(synthesized) );\n      } catch (IOException e) {\n        throw new RuntimeException(e);\n      }\n    }\n    \n    if( suggestions.size() > 0 ) {  // remove duplicates\n      suggestions = new ArrayList<>(new LinkedHashSet<>(suggestions));\n    }\n\n    List<String> reqVidminkyNames = new ArrayList<>();\n    for (String vidm: state.posTagsToFind) {\n      reqVidminkyNames.add(PosTagHelper.VIDMINKY_MAP.get(vidm));\n    }\n\n    List<String> foundVidminkyNames = new ArrayList<>();\n    for (AnalyzedToken token: tokenReadings) {\n      String posTag2 = token.getPOSTag();\n      if( posTag2 != null && posTag2.contains(VIDMINOK_SUBSTR) ) {\n        String vidmName = PosTagHelper.VIDMINKY_MAP.get(posTag2.replaceFirst(\"^.*\"+VIDMINOK_REGEX+\".*$\", \"$1\"));\n        if( foundVidminkyNames.contains(vidmName) ) {","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementPrepNounRule.java#L482-L518","documentation":"In TokenAgreementPrepNounRule.createRuleMatch() (invoked via potentialRuleMatch), preposition-noun agreement suggestions are produced by synthesizer.synthesize(analyzedToken, posTag, true); IOException is wrapped in RuntimeException. This means the Morfologik synthesizer failed to read its dictionary while generating inflected noun/adjective forms.","triggerScenarios":"Preposition-noun case disagreement found in text, rule calls synthesize() to build correct inflected forms, and the dictionary lookup raises IOException (unreadable/corrupt dictionary resource or storage error).","commonSituations":"Corrupted uk language dictionaries in deployment; disk or volume errors; jars damaged by aggressive build filtering or repackaging; memory-constrained environments failing during dictionary load.","solutions":["Read e.getCause() to identify the underlying resource/I/O problem.","Verify and if needed rebuild the Ukrainian dictionary resources in the deployed jar.","Add a startup self-test that synthesizes a known token/posTag pair to fail fast on broken dictionaries.","Catch the RuntimeException at the service boundary and return the disagreement without suggestions.","Ensure your packaging/shading config excludes binary resources from filtering."],"exampleFix":"// before\nString[] synthesized = synthesizer.synthesize(analyzedToken, posTag, true);\n// after\nString[] synthesized;\ntry {\n  synthesized = synthesizer.synthesize(analyzedToken, posTag, true);\n} catch (IOException e) {\n  LOG.warn(\"synthesis failed, no suggestions will be added\", e);\n  synthesized = new String[0];\n}","handlingStrategy":"try-catch","validationCode":"// pre-check synthesizer availability\nObjects.requireNonNull(synthesizer, \"synthesizer not initialized\");\nif (!dictionaryLoaded) throw new IllegalStateException(\"Ukrainian synthesizer dictionary not loaded\");","typeGuard":null,"tryCatchPattern":"try { matches = rule.match(tokens); }\ncatch (RuntimeException e) {\n  if (e.getCause() instanceof IOException) { LOG.warn(\"prep-noun synthesis failed\", e); /* return match without suggestions */ }\n  else throw e;\n}","preventionTips":["Startup self-test: synthesize a known token/posTag pair","Exclude binary dictionaries from build resource filtering","Watch disk/permission errors on hosts running LanguageTool","Return empty suggestions instead of crashing the whole check request"],"tags":["io","synthesizer","suggestions","preposition"],"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"}