HMCL-dev/HMCL · error · ChecksumMismatchException

SHA-1

Error message

SHA-1

What it means

ChecksumMismatchException thrown after a processor output exists but its SHA-1 does not match the value declared in install_profile.json. HMCL deletes the mismatching artifact to avoid leaving a bad file. This is the post-processor integrity gate for Forge installation; note HMCL already falls back to a ZIP-integrity check when non-standard zlib compression changes jar hashes.

Solutions

  1. Ensure the launcher's zlib handling matches the platform (the mismatch may be benign compression difference on zlib-ng systems)
  2. Delete the version's partially installed files and re-run the Forge installation to regenerate outputs
  3. Verify the installer JAR matches the official Forge download (hash), since profile hashes must match the processors
  4. Update HMCL, which tracks known zlib-compression incompatibilities and applies the ZIP-integrity fallback

Example fix

// benign mismatch due to zlib-ng: prefer an HMCL build where IS_ZLIB_COMPATIBLE is false,
// or verify jar integrity manually
try {
    FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(artifact, artifact);
    // jar is structurally valid; hash mismatch from compression is acceptable
} catch (Exception e) {
    Files.delete(artifact); // genuinely bad output
    throw new ChecksumMismatchException("SHA-1", expected, actual);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Preflight: verify the installer matches official hashes so profile SHA-1 expectations are trustworthy
String sha1 = DigestUtils.digestToString("SHA-1", new FileInputStream(installer.toFile()));
if (!officialSha1.equals(sha1)) throw new IOException("Installer hash mismatch, re-download");

Try / catch

try {
    installTask.run();
} catch (ChecksumMismatchException e) {
    // algorithm='SHA-1': retry once after deleting partial outputs;
    // if on zlib-ng systems, use an HMCL build with the ZIP-integrity fallback
}

Prevention

When it happens

Trigger: After running a processor, DigestUtils.digestToString("SHA-1", output) differs from entry.getValue() and the zlib-compatibility fallback (ZIP_INTEGRITY_CHECK_HANDLER) also fails or does not apply, so the artifact is deleted and the exception is raised.

Common situations: zlib-ng or other non-standard compression altering jar bytes on systems where IS_ZLIB_COMPATIBLE is true; a buggy or tampered processor producing wrong output; profile hashes for a different Forge version than the installed one; disk corruption.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/f7d5b5668a1c59ee. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/download/forge/ForgeNewInstallTask.java:183

                if (!Objects.equals(code, entry.getValue())) {
                    if (!ZlibUtils.IS_ZLIB_COMPATIBLE && FileUtils.getExtension(artifact).equals("jar")) {
                        // Forge/NeoForge generates JARs dynamically during installation.
                        // When native compression libraries such as zlib-ng are in use,
                        // the resulting JAR may be compressed differently, causing its
                        // SHA-1 hash to differ from the expected value recorded in the
                        // install profile. In this case, fall back to verifying that the
                        // file is at least a structurally valid ZIP/JAR archive.
                        try {
                            FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER.checkIntegrity(artifact, artifact);
                            LOG.info("Ignoring SHA-1 mismatch for " + artifact + " due to non-standard zlib compression output");
                            continue;
                        } catch (Exception ignored) {
                        }
                    }


                    Files.delete(artifact);
                    throw new ChecksumMismatchException("SHA-1", entry.getValue(), code);
                }
            }
        }
    }

    private final DefaultDependencyManager dependencyManager;
    private final DefaultGameRepository gameRepository;
    private final GameInstanceManifest manifest;
    /// Source vanilla client JAR copied before processors are invoked.
    private final Path minecraftJar;
    private final Path installer;
    private final List<Task<?>> dependents = new ArrayList<>(1);
    private final List<Task<?>> dependencies = new ArrayList<>(1);

    private ForgeNewInstallProfile profile;
    private List<Processor> processors;
    private GameInstanceManifest forgeVersion;
    private final String selfVersion;

View on GitHub (pinned to 24702dc5a0)