HMCL-dev/HMCL · error · IOException

Illegal result:

Error message

Illegal result: 

What it means

In JavaDownloadDialog's Disco (foojay) download flow, the pkgInfoUri metadata is fetched and parsed into a DiscoResult, and the code requires exactly one result entry. If the Disco API returns zero or multiple matching packages, the dialog throws IOException("Illegal result: " + json). It guards against ambiguous or empty upstream download resolution.

Solutions

  1. Pick a different (more common) Java distribution/version or architecture in the dialog and retry
  2. Check the Disco API response (the JSON is appended to the message) to see what was actually returned
  3. Manually download the JDK from the vendor and add it via the Java management page
  4. Update HMCL so its Disco endpoint/parameters match current upstream API behavior

Example fix

// before
if (result.getResult().size() != 1)
    throw new IOException("Illegal result: " + json);
// after
if (result.getResult().isEmpty())
    throw new IOException("No matching package found: " + json);
if (result.getResult().size() > 1)
    LOG.warning("Multiple Disco results, using the first of " + result.getResult().size());
Defensive patterns

Strategy: try-catch

Validate before calling

// query the Disco API before offering the download
HttpResponse<String> resp = client.send(pkgInfoRequest, ofString());
JsonArray results = JsonParser.parseString(resp.body())
    .getAsJsonObject().getAsJsonArray("result");
if (results == null || results.size() != 1)
    throw new IllegalStateException("Disco returned " + (results == null ? 0 : results.size()) + " candidates");

Try / catch

try {
    downloadJava(version);
} catch (IOException e) {
    if (e.getMessage().startsWith("Illegal result:")) {
        Controllers.dialog("No unique Java package found for this version/architecture; choose another distribution");
    } else throw e;
}

Prevention

When it happens

Trigger: Clicking download in the Java download dialog when the foojay Disco API's package-info endpoint returns a result array whose size != 1 (0 matches for the requested distro/version/ architecture, or 2+ ambiguous matches).

Common situations: Requesting an unusual Java version/arch/libc combination the Disco API maps to multiple or zero artifacts; upstream API schema or data changes; stale version metadata links from the version manifest.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java:380

            }
        }

        private void onDownload() {
            fireEvent(new DialogCloseEvent());

            DiscoJavaDistribution distribution = distributionBox.getSelectionModel().getSelectedItem();
            DiscoJavaRemoteVersion version = remoteVersionBox.getSelectionModel().getSelectedItem();
            JavaPackageType packageType = packageTypeBox.getSelectionModel().getSelectedItem();

            if (version == null)
                return;

            Controllers.taskDialog(new GetTask(downloadProvider.injectURLWithCandidates(version.getLinks().pkgInfoUri()))
                    .setExecutor(Schedulers.io())
                    .thenComposeAsync(json -> {
                        DiscoResult<DiscoRemoteFileInfo> result = JsonUtils.fromNonNullJson(json, DiscoResult.typeOf(DiscoRemoteFileInfo.class));
                        if (result.getResult().size() != 1)
                            throw new IOException("Illegal result: " + json);

                        DiscoRemoteFileInfo fileInfo = result.getResult().get(0);
                        if (StringUtils.isNotBlank(fileInfo.checksumType())
                                && !fileInfo.checksumType().equals("sha1") && !fileInfo.checksumType().equals("sha256") && !fileInfo.checksumType().equals("md5"))
                            throw new IOException("Unsupported checksum type: " + fileInfo.checksumType());
                        if (StringUtils.isBlank(fileInfo.directDownloadUri()))
                            throw new IOException("Missing download URI: " + json);

                        Path targetFile = Files.createTempFile("hmcl-java-", "." + version.getArchiveType());
                        targetFile.toFile().deleteOnExit();

                        Task<FileDownloadTask.IntegrityCheck> getIntegrityCheck;
                        if (StringUtils.isNotBlank(fileInfo.checksum()))
                            getIntegrityCheck = Task.completed(new FileDownloadTask.IntegrityCheck(fileInfo.checksumType(), fileInfo.checksum()));
                        else if (StringUtils.isNotBlank(fileInfo.checksumUri()))
                            getIntegrityCheck = new GetTask(downloadProvider.injectURLWithCandidates(fileInfo.checksumUri()))
                                    .thenApplyAsync(checksum -> {
                                        checksum = checksum.trim();

View on GitHub (pinned to 24702dc5a0)