{"record":{"id":"ed274fd86c9dd162","repo":"HMCL-dev/HMCL","slug":"no-download-url-is-available","errorCode":null,"errorMessage":"No download url is available","messagePattern":"No download url is available","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java","lineNumber":44,"sourceCode":"import org.jetbrains.annotations.NotNull;\n\nimport java.io.IOException;\nimport java.util.Optional;\n\npublic record RemoteVersion(UpdateChannel channel, String version, String url, Type type, IntegrityCheck integrityCheck,\n                            boolean preview, boolean force) {\n\n    public static RemoteVersion fetch(UpdateChannel channel, boolean preview, String url) throws IOException {\n        try {\n            JsonObject response = JsonUtils.fromNonNullJson(NetworkUtils.doGet(url), JsonObject.class);\n            String version = Optional.ofNullable(response.get(\"version\")).map(JsonElement::getAsString).orElseThrow(() -> new IOException(\"version is missing\"));\n            String jarUrl = Optional.ofNullable(response.get(\"jar\")).map(JsonElement::getAsString).orElse(null);\n            String jarHash = Optional.ofNullable(response.get(\"jarsha1\")).map(JsonElement::getAsString).orElse(null);\n            boolean force = Optional.ofNullable(response.get(\"force\")).map(JsonElement::getAsBoolean).orElse(false);\n            if (jarUrl != null && jarHash != null) {\n                return new RemoteVersion(channel, version, jarUrl, Type.JAR, new IntegrityCheck(\"SHA-1\", jarHash), preview, force);\n            } else {\n                throw new IOException(\"No download url is available\");\n            }\n        } catch (JsonParseException e) {\n            throw new IOException(\"Malformed response\", e);\n        }\n    }\n\n    @Override\n    public @NotNull String toString() {\n        return \"[\" + version + \" from \" + url + \"]\";\n    }\n\n    public enum Type {\n        JAR\n    }\n}\n","sourceCodeStart":26,"sourceCodeEnd":60,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/upgrade/RemoteVersion.java#L26-L60","documentation":"RemoteVersion.fetch queries HMCL's update metadata endpoint and expects a JSON object containing both \"jar\" (download URL) and \"jarsha1\" (hash). If either is missing so a JAR-type RemoteVersion cannot be built, it throws IOException(\"No download url is available\"). This protects against update metadata that lacks a downloadable artifact.","triggerScenarios":"Checking for updates when the server's metadata JSON has no \"jar\" or no \"jarsha1\" entry (null from Optional.orElse(null)) — the channel responds, but without a usable artifact link.","commonSituations":"Update server misconfiguration; a channel serving metadata-only entries (e.g. announcing updates distributed another way); partial/cached JSON responses; unofficial or deprecated update channels.","solutions":["Retry later — the update server metadata may be temporarily incomplete","Switch to a different update channel in HMCL settings","Download the latest HMCL jar manually from the official site and replace the current one","If operating the update server, populate the \"jar\" and \"jarsha1\" fields in the channel metadata"],"exampleFix":"// before\nif (jarUrl != null && jarHash != null) {\n    return new RemoteVersion(...);\n} else {\n    throw new IOException(\"No download url is available\");\n}\n// after\nif (jarUrl != null && jarHash != null) {\n    return new RemoteVersion(...);\n} else {\n    throw new IOException(\"No download url is available for channel \" + channel\n        + \" version \" + version + \" (jar=\" + jarUrl + \")\");\n}","handlingStrategy":"fallback","validationCode":"// probe metadata before trusting it\nJsonObject meta = JsonParser.parseString(body).getAsJsonObject();\nif (!meta.has(\"jar\") || !meta.has(\"jarsha1\")) {\n    // channel metadata incomplete: fall back to manual download\n}","typeGuard":null,"tryCatchPattern":"try {\n    RemoteVersion v = RemoteVersion.fetch(channel, version, preview);\n} catch (IOException e) {\n    if (e.getMessage().equals(\"No download url is available\")) {\n        openOfficialDownloadPage(); // manual update path\n    } else throw e;\n}","preventionTips":["Retry the update check later; server metadata may be temporarily incomplete","Keep a manual-update fallback (official website) wired into the UI","If you run the update server, validate that jar and jarsha1 are always populated"],"tags":["update","download","metadata","network"],"backgroundTag":"missing-required-argument","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"}