{"record":{"id":"ad67e24beadae3da","repo":"languagetool-org/languagetool","slug":"ioexception-while-synthesizing-suggestions-numr-n","errorCode":null,"errorMessage":"IOException while synthesizing suggestions (numr-noun agreement)","messagePattern":"IOException while synthesizing suggestions \\(numr-noun agreement\\)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementNumrNounRule.java","lineNumber":597,"sourceCode":"\n              for (String s : synthesized) {\n\n                if( numrCleanToken.equalsIgnoreCase(\"півтора\")\n                    && nounToken.getLemma().equals(\"раз\") && ! s.equals(\"раза\") )\n                  continue;\n\n                String suggestion = state.numrAnalyzedTokenReadings.getToken();\n                for(int j=state.numrPos+1; j<state.nounPos; j++ ) {\n                  suggestion += \" \" + tokens[j].getToken(); // add middle adj\n                }\n                suggestion += \" \" + s;\n                \n                if( ! suggestions.contains(suggestion) ) {\n                  suggestions.add(suggestion);\n                }\n              }\n            } catch (IOException e) {\n              throw new RuntimeException(e);\n            }\n          }\n        }\n        }\n\n        if( suggestions.size() > 0 ) {\n            potentialRuleMatch.setSuggestedReplacements(suggestions);\n        }\n\n        ruleMatches.add(potentialRuleMatch);\n      }\n\n      state.reset();\n    }\n\n    return toRuleMatchArray(ruleMatches);\n  }\n","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-language-modules/uk/src/main/java/org/languagetool/rules/uk/TokenAgreementNumrNounRule.java#L579-L615","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the cause chain for the original IOException and fix the storage/resource issue.","Validate the dictionary resources in the deployed artifact (checksums, jar listing).","Redeploy a clean build of languagetool-language-modules/uk.","Wrap rule execution so a synthesis failure degrades to a suggestion-less match instead of crashing the check run.","Pin and verify artifact checksums in CI/CD to catch corrupted jars early."],"exampleFix":"// before\n} catch (IOException e) {\n  throw new RuntimeException(e);\n}\n// after\n} catch (IOException e) {\n  LOG.warn(\"numr-noun suggestion synthesis failed\", e);\n  suggestions.clear(); // report disagreement without inflected suggestions\n}","handlingStrategy":"try-catch","validationCode":"// verify dictionary resource presence and readability\ntry (InputStream in = getClass().getResourceAsStream(\"/uk/ukrainian_synth.dict\")) {\n  if (in == null || in.read() == -1) throw new IllegalStateException(\"Synth dictionary empty/missing\");\n}","typeGuard":null,"tryCatchPattern":"try { matches = rule.match(tokens); }\ncatch (RuntimeException e) {\n  if (e.getCause() instanceof IOException) { LOG.warn(\"numr-noun synthesis I/O failure\", e); matches = Collections.emptyList(); }\n  else throw e;\n}","preventionTips":["Validate artifact integrity (checksums) in the deploy pipeline","Test agreement rules over sample sentences in CI","Monitor RuntimeException-with-IOException-cause rates in production","Ensure sufficient disk health where dictionaries are memory-mapped"],"tags":["io","synthesizer","numerals","agreement-rule"],"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-14T05:17:10.506Z"}