{"record":{"id":"70519d535a27715c","repo":"HMCL-dev/HMCL","slug":"file-name-has-incorrect-sha-1-hash-expected","errorCode":null,"errorMessage":"File ${name} has incorrect SHA-1 hash: expected ${expected}, got ${actual}","messagePattern":"File (.+?) has incorrect SHA-1 hash: expected (.+?), got (.+?)","errorType":"exception","errorClass":"ArtifactMalformedException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloadTask.java","lineNumber":132,"sourceCode":"                    }\n\n                    Path tempFile = tempDir.resolve(entry.getKey() + \".lzma\");\n                    var task = new FileDownloadTask(downloadProvider.injectURLWithCandidates(download.getUrl()), tempFile,\n                            new FileDownloadTask.IntegrityCheck(\"SHA-1\", download.getSha1()));\n                    task.setName(entry.getKey());\n                    dependencies.add(task.thenRunAsync(() -> {\n                        Path decompressed = tempDir.resolve(entry.getKey() + \".tmp\");\n                        var digest = MessageDigest.getInstance(\"SHA-1\");\n                        try (var input = new DigestInputStream(new LZMAInputStream(Files.newInputStream(tempFile)), digest)) {\n                            Files.copy(input, decompressed, StandardCopyOption.REPLACE_EXISTING);\n                        } catch (IOException e) {\n                            throw new ArtifactMalformedException(\"File \" + entry.getKey() + \" is malformed\", e);\n                        }\n\n                        String actualSha1 = HexFormat.of().formatHex(digest.digest());\n\n                        if (rawSha1 != null && !actualSha1.equalsIgnoreCase(rawSha1)) {\n                            throw new ArtifactMalformedException(\"File \" + entry.getKey() + \" has incorrect SHA-1 hash: expected \" + rawSha1 + \", got \" + actualSha1);\n                        }\n\n                        try {\n                            Files.deleteIfExists(tempFile);\n                        } catch (IOException e) {\n                            LOG.warning(\"Failed to delete temporary file: \" + tempFile, e);\n                        }\n\n                        Files.move(decompressed, dest, StandardCopyOption.REPLACE_EXISTING);\n                        if (file.isExecutable()) {\n                            FileUtils.setExecutable(dest);\n                        }\n                    }));\n                } else if (file.getDownloads().containsKey(\"raw\")) {\n                    DownloadInfo download = file.getDownloads().get(\"raw\");\n                    var task = new FileDownloadTask(downloadProvider.injectURLWithCandidates(download.getUrl()), dest, new FileDownloadTask.IntegrityCheck(\"SHA-1\", download.getSha1()));\n                    task.setName(entry.getKey());\n                    if (file.isExecutable()) {","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/download/java/mojang/MojangJavaDownloadTask.java#L114-L150","documentation":"After decompressing a runtime file, execute() compares the computed SHA-1 with the expected hash from Mojang's manifest. On mismatch it throws ArtifactMalformedException stating expected vs actual hash, preventing an integrity-compromised Java runtime from being installed.","triggerScenarios":"Decompressed output's DigestInputStream digest differs from the `rawSha1` recorded in MojangJavaRemoteFiles for that entry (rawSha1 non-null and case-insensitively unequal).","commonSituations":"Corrupted download (bit flips, truncated archive that still decompresses); CDN/proxy serving modified content; interrupted disk write; rarely, Mojang updating the file without updating clients' cached manifest.","solutions":["Delete the downloaded Java runtime archive and temporary files, then re-download.","Switch download provider/mirror to get the file from a different source.","Verify disk health/free space; retry on a stable connection.","Update HMCL so the manifest and expected hashes are current."],"exampleFix":"// Recovery, not code:\n// rm -rf <hmcl-data>/java/<runtime> ; re-run the Java runtime download task","handlingStrategy":"retry","validationCode":"// Verify downloaded archive hash against manifest before decompressing\nString sha1 = Hashing.sha1().hashBytes(Files.readAllBytes(archive)).toString();\nif (!sha1.equalsIgnoreCase(expectedArchiveSha1)) { deleteAndRedownload(); }","typeGuard":"null","tryCatchPattern":"try { task.run(); } catch (ArtifactMalformedException e) {\n    if (e.getMessage().contains(\"SHA-1\")) { purgeRuntimeCache(); retryOnce(); }\n}","preventionTips":["Always verify the top-level archive checksum before extraction.","Avoid unreliable proxies/CDNs that can alter content.","Delete old cached runtime archives when Mojang refreshes the manifest."],"tags":["checksum","sha1","download","integrity"],"backgroundTag":"checksum-mismatch","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}