{"record":{"id":"f9e0191e63f31c8f","repo":"HMCL-dev/HMCL","slug":"missing-download-uri","errorCode":null,"errorMessage":"Missing download URI: ","messagePattern":"Missing download URI: ","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java","lineNumber":387,"sourceCode":"            DiscoJavaRemoteVersion version = remoteVersionBox.getSelectionModel().getSelectedItem();\n            JavaPackageType packageType = packageTypeBox.getSelectionModel().getSelectedItem();\n\n            if (version == null)\n                return;\n\n            Controllers.taskDialog(new GetTask(downloadProvider.injectURLWithCandidates(version.getLinks().pkgInfoUri()))\n                    .setExecutor(Schedulers.io())\n                    .thenComposeAsync(json -> {\n                        DiscoResult<DiscoRemoteFileInfo> result = JsonUtils.fromNonNullJson(json, DiscoResult.typeOf(DiscoRemoteFileInfo.class));\n                        if (result.getResult().size() != 1)\n                            throw new IOException(\"Illegal result: \" + json);\n\n                        DiscoRemoteFileInfo fileInfo = result.getResult().get(0);\n                        if (StringUtils.isNotBlank(fileInfo.checksumType())\n                                && !fileInfo.checksumType().equals(\"sha1\") && !fileInfo.checksumType().equals(\"sha256\") && !fileInfo.checksumType().equals(\"md5\"))\n                            throw new IOException(\"Unsupported checksum type: \" + fileInfo.checksumType());\n                        if (StringUtils.isBlank(fileInfo.directDownloadUri()))\n                            throw new IOException(\"Missing download URI: \" + json);\n\n                        Path targetFile = Files.createTempFile(\"hmcl-java-\", \".\" + version.getArchiveType());\n                        targetFile.toFile().deleteOnExit();\n\n                        Task<FileDownloadTask.IntegrityCheck> getIntegrityCheck;\n                        if (StringUtils.isNotBlank(fileInfo.checksum()))\n                            getIntegrityCheck = Task.completed(new FileDownloadTask.IntegrityCheck(fileInfo.checksumType(), fileInfo.checksum()));\n                        else if (StringUtils.isNotBlank(fileInfo.checksumUri()))\n                            getIntegrityCheck = new GetTask(downloadProvider.injectURLWithCandidates(fileInfo.checksumUri()))\n                                    .thenApplyAsync(checksum -> {\n                                        checksum = checksum.trim();\n\n                                        int idx = checksum.indexOf(' ');\n                                        if (idx > 0)\n                                            checksum = checksum.substring(0, idx);\n\n                                        return new FileDownloadTask.IntegrityCheck(fileInfo.checksumType(), checksum);\n                                    });","sourceCodeStart":369,"sourceCodeEnd":405,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/ui/main/JavaDownloadDialog.java#L369-L405","documentation":"The Disco download flow requires a direct download URI in the resolved package info. If DiscoRemoteFileInfo.directDownloadUri() is blank, the dialog throws IOException(\"Missing download URI: \" + json) because it has nowhere to download the JDK archive from.","triggerScenarios":"Downloading Java via the Disco API when the returned package entry has an empty/absent directDownloadUri field — the API resolved the query but returned only metadata without a direct link.","commonSituations":"Distributions that only expose indirect download pages; upstream API response shape changes; network proxies/CDN stripping fields; requests for combinations where foojay has no direct artifact link.","solutions":["Retry with a different Java distribution or version in the dialog","Inspect the JSON in the error message to confirm directDownloadUri is absent","Download the JDK manually from the vendor site and add it via Java management","Update HMCL in case the upstream API changed field names/semantics"],"exampleFix":"// before\nif (StringUtils.isBlank(fileInfo.directDownloadUri()))\n    throw new IOException(\"Missing download URI: \" + json);\n// after\nif (StringUtils.isBlank(fileInfo.directDownloadUri()))\n    throw new IOException(\"Missing download URI for \" + version.getDistributionName()\n        + \"; try a different distribution or download manually\");","handlingStrategy":"validation","validationCode":"// before initiating the download task\nJsonObject info = results.get(0).getAsJsonObject();\nString uri = info.has(\"directDownloadUri\") && !info.get(\"directDownloadUri\").isJsonNull()\n    ? info.get(\"directDownloadUri\").getAsString() : null;\nif (StringUtils.isBlank(uri)) {\n    throw new IllegalStateException(\"Disco entry has no direct download URI; pick another distribution\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    downloadJava(version);\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Missing download URI:\")) {\n        openVendorDownloadPage(version.getDistributionName());\n    } else throw e;\n}","preventionTips":["Choose distributions that publish direct download links on foojay","Fallback to manual vendor download when metadata lacks a URI","Cache last-known-good metadata to detect upstream regressions"],"tags":["download","api","empty-field","java"],"backgroundTag":"empty-required-field","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"}