HMCL-dev/HMCL · error · IOException

Malformed response\n" + text

Error message

Malformed response\n" + text

What it means

AuthlibInjectorServer.refreshMetadata parses the server's metadata response body; if JSON parsing fails it wraps the JsonParseException in an IOException "Malformed response\n" + the raw text. This means the remote server did not return valid authlib-injector metadata JSON.

Solutions

  1. Verify the URL points to a real authlib-injector (Yggdrasil) API root, not a website landing page
  2. Inspect the raw response text (included in the exception) to see what the server returned
  3. Retry when behind a captive portal or proxy, or use a different network
  4. Check the server's status page; the instance may be down or misconfigured

Example fix

// before
server = AuthlibInjectorServer.locateServer("https://example.com/"); // HTML page
// after
server = AuthlibInjectorServer.locateServer("https://auth.server.example/api/yggdrasil");
Defensive patterns

Strategy: try-catch

Validate before calling

// optionally pre-check that the URL responds with JSON
String body = httpGetString(url);
if (body == null || body.isBlank() || !body.strip().startsWith("{")) {
    throw new IOException("Server did not return JSON metadata");
}

Try / catch

try {
    AuthlibInjectorServer server = AuthlibInjectorServer.locateServer(url);
} catch (IOException e) {
    ui.showError("Server returned malformed metadata: " + e.getMessage());
}

Prevention

When it happens

Trigger: Calling locateServer/refreshMetadata against a URL whose HTTP response body is not valid JSON (HTML error page, empty body, proxy interstitial, wrong service).

Common situations: Entering a non-authlib-injector URL (landing page or HTML status page); captive portals/proxies returning HTML; server returning 200 with an error page; truncated responses.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/auth/authlibinjector/AuthlibInjectorServer.java:157

    }

    public String fetchMetadataResponse() throws IOException {
        if (metadataResponse == null || !metadataRefreshed) {
            refreshMetadata();
        }
        return getMetadataResponse().get();
    }

    public void refreshMetadata() throws IOException {
        refreshMetadata(HttpRequest.GET(url).getString());
    }

    private void refreshMetadata(String text) throws IOException {
        long timestamp = System.currentTimeMillis();
        try {
            setMetadataResponse(text, timestamp);
        } catch (JsonParseException e) {
            throw new IOException("Malformed response\n" + text, e);
        }

        metadataRefreshed = true;
        LOG.info("authlib-injector server metadata refreshed: " + url);
        Platform.runLater(helper::invalidate);
    }

    private void setMetadataResponse(String metadataResponse, long metadataTimestamp) throws JsonParseException {
        JsonObject response = GSON.fromJson(metadataResponse, JsonObject.class);
        if (response == null) {
            throw new JsonParseException("Metadata response is empty");
        }

        synchronized (this) {
            this.metadataResponse = metadataResponse;
            this.metadataTimestamp = metadataTimestamp;

            Optional<JsonObject> metaObject = tryCast(response.get("meta"), JsonObject.class);

View on GitHub (pinned to 24702dc5a0)