{"record":{"id":"34d436b4646eb3a9","repo":"languagetool-org/languagetool","slug":"checksum-mismatch-for-the-file-path-expected","errorCode":null,"errorMessage":"Checksum mismatch for the file '${path}': expected ${requiredHash}, got ${computedHash}","messagePattern":"Checksum mismatch for the file '(.+?)': expected (.+?), got (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/tools/Tools.java","lineNumber":285,"sourceCode":"    InputStream is = JLanguageTool.getDataBroker().getAsStream(path);\n    if (is == null) {\n      throw new IOException(\"Could not load file from classpath: '\" + path + \"'\");\n    }\n    return is;\n  }\n\n  public static InputStream getStream(String path, String requiredHash) throws IOException, NoSuchAlgorithmException {\n    byte[] data;\n\n    try (InputStream is = getStream(path)) {\n      data = is.readAllBytes();\n    }\n\n    MessageDigest md = MessageDigest.getInstance(\"SHA-256\");\n    String computedHash = HexFormat.of().formatHex(md.digest(data));\n\n    if (!computedHash.equals(requiredHash)) {\n      throw new IOException(\"Checksum mismatch for the file '\" + path + \"': expected \" + requiredHash + \", got \" + computedHash);\n    }\n    return new ByteArrayInputStream(data);\n  }\n\n  /**\n   * Enable and disable rules of the given LanguageTool instance.\n   * @param lt LanguageTool object\n   * @param disabledRuleIds ids of the rules to be disabled\n   * @param enabledRuleIds ids of the rules to be enabled\n   * @param useEnabledOnly if set to {@code true}, disable all rules except those enabled explicitly\n   */\n  public static void selectRules(JLanguageTool lt, List<String> disabledRuleIds, List<String> enabledRuleIds, boolean useEnabledOnly) {\n    Set<String> disabledRuleIdsSet = new HashSet<>();\n    disabledRuleIdsSet.addAll(disabledRuleIds);\n    Set<String> enabledRuleIdsSet = new HashSet<>();\n    enabledRuleIdsSet.addAll(enabledRuleIds);\n    selectRules(lt, Collections.emptySet(), Collections.emptySet(), disabledRuleIdsSet, enabledRuleIdsSet, useEnabledOnly, false);\n  }","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/tools/Tools.java#L267-L303","documentation":"Tools.getStream reads a file fully, computes its SHA-256 hash, and compares it against a caller-supplied required hash before returning the data as a stream. An IOException with this message is thrown when the content has changed or the expected hash is wrong, guaranteeing callers never process tampered or stale data.","triggerScenarios":"Calling Tools.getStream(path, requiredHash) where the file bytes changed after the expected hash was recorded, the hash was computed on a different file/version, or the hash string itself is malformed/outdated.","commonSituations":"Downloading cached language-model or resource files whose upstream content was updated; reusing a pinned hash across releases; manual edits to a data file after hashing.","solutions":["Recompute the expected SHA-256 hash from the current file content (shasum -a 256 <path>) and pass that as requiredHash","Re-download or restore the original file from the trusted source that matches requiredHash","If the file legitimately changed, update the pinned hash in the calling code/config","Check for proxy or transfer corruption by re-fetching the file and comparing hashes"],"exampleFix":"// before\nInputStream in = Tools.getStream(path, \"abc123oldhash\");\n// after\nString hash = HexFormat.of().formatHex(MessageDigest.getInstance(\"SHA-256\").digest(Files.readAllBytes(Path.of(path))));\nInputStream in = Tools.getStream(path, hash);","handlingStrategy":"validation","validationCode":"String actual = HexFormat.of().formatHex(MessageDigest.getInstance(\"SHA-256\").digest(Files.readAllBytes(Path.of(path))));\nif (!actual.equals(requiredHash)) throw new IOException(\"Checksum mismatch: \" + path);\nInputStream in = Tools.getStream(path, requiredHash);","typeGuard":null,"tryCatchPattern":"try (InputStream in = Tools.getStream(path, requiredHash)) { ... } catch (IOException e) { if (e.getMessage().startsWith(\"Checksum mismatch\")) { reDownloadFile(path); } else { throw e; } }","preventionTips":["Recompute hashes from current file content instead of hard-coding them","Pin hashes per release and regenerate them on dependency upgrades","Verify file integrity after download before calling getStream"],"tags":["checksum","sha-256","file-integrity"],"backgroundTag":"checksum-mismatch","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"}