HMCL-dev/HMCL · error · IOException

Self verification failed

Error message

Self verification failed

What it means

applyUpdate copies the current running JAR over the update target to finalize the update. Before doing so it requires the running JAR to be self-verified (unless DISABLE_SELF_INTEGRITY_CHECK is set); otherwise it throws this IOException, refusing to propagate a binary that could have been tampered with.

Solutions

  1. Run the official, unmodified HMCL JAR when applying updates
  2. Rebuild with the official build pipeline so the JAR passes IntegrityChecker
  3. Check the JAR for accidental modification (e.g. re-zipping breaks the signature) and re-download
  4. As a last resort for dev builds, set the disable-self-integrity-check property at launch

Example fix

// before
java -jar my-custom-build.jar (then applying update fails)
// after
java -jar HMCL-official.jar
// or dev build:
java -Dhmcl.self.integrity.check.disable=true -jar my-custom-build.jar
Defensive patterns

Strategy: try-catch

Validate before calling

if (!IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK && !IntegrityChecker.isSelfVerified()) {
    return; // skip applying update on unverified jar
}

Try / catch

try {
    handler.applyUpdate(target);
} catch (IOException e) {
    LOG.severe("Update aborted: running jar failed self verification", e);
    // fall back to keeping the current version
}

Prevention

When it happens

Trigger: applyUpdate (reached via processArguments) is invoked while IntegrityChecker.isSelfVerified() returns false and DISABLE_SELF_INTEGRITY_CHECK is false.

Common situations: Launching HMCL from a self-compiled or modified JAR and then applying a pending update; a corrupted JAR on disk; running unpacked classes instead of the distributed JAR.

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/816e415261bda3fc. Report an issue: GitHub.

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/upgrade/UpdateHandler.java:175

                    }

                } else {
                    Exception e = executor.getException();
                    LOG.warning("Failed to update to " + version, e);
                    if (!(e instanceof CancellationException)) {
                        Platform.runLater(() -> Controllers.dialog(e.toString(), i18n("update.failed"), MessageType.ERROR));
                    }
                }
            });
        }));
    }

    private static void applyUpdate(Path target) throws IOException {
        LOG.info("Applying update to " + target);

        Path self = getCurrentLocation();
        if (!IntegrityChecker.DISABLE_SELF_INTEGRITY_CHECK && !IntegrityChecker.isSelfVerified()) {
            throw new IOException("Self verification failed");
        }
        ExecutableHeaderHelper.copyWithHeader(self, target);

        Optional<Path> newFilename = tryRename(target, Metadata.VERSION);
        if (newFilename.isPresent()) {
            LOG.info("Move " + target + " to " + newFilename.get());
            try {
                Files.move(target, newFilename.get());
                target = newFilename.get();
            } catch (IOException e) {
                LOG.warning("Failed to move target", e);
            }
        }

        startJava(target);
    }

    private static void requestUpdate(Path updateTo, Path self) throws IOException {

View on GitHub (pinned to 24702dc5a0)