HMCL-dev/HMCL · error · IOException
Missing release file
Error message
Missing release file
What it means
JavaInfo.fromArchive requires the JDK root directory inside the archive to contain a 'release' file — the standard marker file JDK distributions ship with version info (JAVA_VERSION, vendor, etc.). It throws IOException("Missing release file") when that entry is absent, because version metadata cannot be parsed without it.
Solutions
- Use a complete JDK distribution archive that includes the 'release' file at the JDK root.
- If building a custom runtime with jlink, generate a release file or obtain JavaInfo another way.
- Re-download the distribution from the vendor; a partial download may have dropped entries.
- Catch the IOException and fall back to running 'java -version' on the extracted binary to detect the version.
Defensive patterns
Strategy: validation
Validate before calling
E releaseEntry = tree.getRoot().getSubDirs().values().iterator().next().getFiles().get("release");
if (releaseEntry == null) {
throw new IOException("Archive JDK root has no 'release' file; not a full JDK distribution");
} Try / catch
try {
JavaInfo info = JavaInfo.fromArchive(tree);
} catch (IOException e) {
if (e.getMessage().contains("Missing release file")) {
// fall back to running java -version on the extracted binary
}
} Prevention
- Only use full JDK distributions that include the release marker file
- Avoid jlink-minimized or manually assembled runtimes when metadata detection is needed
- Check archive integrity/checksums after download
When it happens
Trigger: JavaInfo.fromArchive(tree) succeeds the single-root-directory check, but jdkRoot.getFiles().get("release") returns null — the JDK directory inside the archive has no 'release' file at its root.
Common situations: Using a JRE-only or custom-built distribution that omits the release file; manually assembled JDK directories; some minimal/minimal-jlink images; archives stripped of metadata files.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Missing java executable file
- Game processor file not found, should be downloaded in…
- `instance.cfg` not found,
- name existing
- Texture url is empty
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/4bbab79200edcaa9.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java:95
throw new IOException("Unknown operating system: " + osName);
if (arch == Architecture.UNKNOWN)
throw new IOException("Unknown architecture: " + osArch);
if (javaVersion == null)
throw new IOException("Missing Java version");
return new JavaInfo(Platform.getPlatform(os, arch), javaVersion, vendor);
}
public static <F, E extends ArchiveEntry> JavaInfo fromArchive(ArchiveFileTree<F, E> tree) throws IOException {
if (tree.getRoot().getSubDirs().size() != 1 || !tree.getRoot().getFiles().isEmpty())
throw new IOException();
ArchiveFileTree.Dir<E> jdkRoot = tree.getRoot().getSubDirs().values().iterator().next();
E releaseEntry = jdkRoot.getFiles().get("release");
if (releaseEntry == null)
throw new IOException("Missing release file");
JavaInfo info;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(tree.getInputStream(releaseEntry), StandardCharsets.UTF_8))) {
info = JavaInfo.fromReleaseFile(reader);
}
ArchiveFileTree.Dir<E> binDir = jdkRoot.getSubDirs().get("bin");
if (binDir == null || binDir.getFiles().get(info.getPlatform().getOperatingSystem().getJavaExecutable()) == null)
throw new IOException("Missing java executable file");
return info;
}
public static String normalizeVendor(String vendor) {
if (vendor == null)
return null;
return switch (vendor) {View on GitHub (pinned to 24702dc5a0)