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
- Pick a different (more common) Java distribution/version or architecture in the dialog and retry
- Check the Disco API response (the JSON is appended to the message) to see what was actually returned
- Manually download the JDK from the vendor and add it via the Java management page
- 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
- Prefer common distribution/version/architecture combinations that map to exactly one Disco result
- Keep HMCL updated for current foojay API parameter semantics
- Have a fallback path: manual JDK download + add via Java management
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
- Malformed response
- Malformed response\n" + text
- Metadata response is empty
- GameRemoteVersions.versions cannot be null
- Unable to parse server manifest.json from
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)