HMCL-dev/HMCL · error · IOException

Bad Implementation-Title

Error message

Bad Implementation-Title

What it means

AuthlibInjectorArtifactInfo.from inspects the jar manifest and requires Implementation-Title to equal "authlib-injector"; any other title throws IOException "Bad Implementation-Title". This verifies that the located artifact really is an authlib-injector build, not an arbitrary jar.

Solutions

  1. Download the artifact from the official authlib-injector release so the manifest is correct
  2. Verify the jar's manifest Implementation-Title before passing it to from()
  3. Re-download the file if it was renamed, rebuilt, or corrupted

Example fix

// before
Path jar = Path.of("some-random.jar");
AuthlibInjectorArtifactInfo info = AuthlibInjectorArtifactInfo.from(jar);
// after
// verify manifest before calling
try (JarFile jf = new JarFile(jar.toFile())) {
    String title = jf.getManifest().getMainAttributes().getValue("Implementation-Title");
    if ("authlib-injector".equals(title)) {
        AuthlibInjectorArtifactInfo info = AuthlibInjectorArtifactInfo.from(jar);
    }
}
Defensive patterns

Strategy: try-catch

Validate before calling

try (JarFile jf = new JarFile(jar.toFile())) {
    String title = jf.getManifest().getMainAttributes().getValue("Implementation-Title");
    if (!"authlib-injector".equals(title)) {
        throw new IOException("Not an authlib-injector artifact: " + title);
    }
}

Try / catch

try {
    AuthlibInjectorArtifactInfo info = AuthlibInjectorArtifactInfo.from(path);
} catch (IOException e) {
    log.error("Invalid authlib-injector artifact at {}: {}", path, e.getMessage());
    // trigger re-download
}

Prevention

When it happens

Trigger: Calling AuthlibInjectorArtifactInfo.from(Path) on a jar whose manifest Implementation-Title differs from "authlib-injector" (or whose jar/manifest cannot be read as expected).

Common situations: Pointing the downloader/library path at a renamed or unrelated jar; a corrupted or rebuilt artifact with wrong manifest attributes; tampered mirror downloads.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorArtifactInfo.java:37

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;
import java.util.jar.Attributes;
import java.util.jar.JarFile;

public record AuthlibInjectorArtifactInfo(int buildNumber, String version, Path location) {

    public static AuthlibInjectorArtifactInfo from(Path location) throws IOException {
        try (JarFile jarFile = new JarFile(location.toFile())) {
            Attributes attributes = jarFile.getManifest().getMainAttributes();

            String title = Optional.ofNullable(attributes.getValue("Implementation-Title"))
                    .orElseThrow(() -> new IOException("Missing Implementation-Title"));
            if (!"authlib-injector".equals(title)) {
                throw new IOException("Bad Implementation-Title");
            }

            String version = Optional.ofNullable(attributes.getValue("Implementation-Version"))
                    .orElseThrow(() -> new IOException("Missing Implementation-Version"));

            int buildNumber;
            try {
                buildNumber = Optional.ofNullable(attributes.getValue("Build-Number"))
                        .map(Integer::parseInt)
                        .orElseThrow(() -> new IOException("Missing Build-Number"));
            } catch (NumberFormatException e) {
                throw new IOException("Bad Build-Number", e);
            }
            return new AuthlibInjectorArtifactInfo(buildNumber, version, location.toAbsolutePath());
        }
    }

    @Override

View on GitHub (pinned to 24702dc5a0)