HMCL-dev/HMCL · error · IOException

/assets/

Error message

/assets/

What it means

Validation failure: an Mcbbs modpack manifest must declare a non-null files array listing every file in the pack. A manifest without files cannot be installed or completed, so validate() rejects it with JsonParseException.

Solutions

  1. Add a "files" array (possibly empty []) to the manifest JSON
  2. Re-export/re-download the modpack with a spec-compliant tool
  3. Validate the manifest against the Mcbbs modpack spec before importing

Example fix

// before
{"manifestType": "minecraftModpack"}
// after
{"manifestType": "minecraftModpack", "files": [], "addons": []}
Defensive patterns

Strategy: validation

Validate before calling

if (!manifest.has("files") || manifest.get("files").isJsonNull())
    throw new IllegalArgumentException("Manifest missing files array");

Try / catch

try { manifest.validate(); } catch (JsonParseException e) { /* report missing field to user */ }

Prevention

When it happens

Trigger: Importing an Mcbbs pack whose manifest JSON lacks the "files" field or has it explicitly null.

Common situations: Hand-crafted or minimal manifests missing the files section; packs exported by broken tools; manifests for server-side-only packs with files omitted instead of an empty array.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameLauncher.java:202

    private Path extractLwjglUnsafeAgent() throws IOException {
        String agentVersion = JarUtils.getAttribute("hmcl.lwjgl-unsafe-agent.version", null);
        if (agentVersion == null) {
            throw new IOException("Missing hmcl.lwjgl-unsafe-agent.version attribute");
        }

        Library library = new Library(new Artifact("org.glavo", "lwjgl-unsafe-agent", agentVersion));
        String fileName = library.artifact().getFileName();

        Path agentPath = instance.getLayout().getLibraryFile(instance.getId(), library).toAbsolutePath().normalize();
        if (agentPath.toString().contains("=")) {
            throw new IOException("Invalid library path: " + agentPath);
        }

        byte[] bytes;
        try (InputStream input = DefaultLauncher.class.getResourceAsStream("/assets/" + fileName)) {
            if (input == null) {
                throw new IOException("/assets/" + fileName + " not found");
            }

            bytes = input.readAllBytes();
        }

        if (Files.isRegularFile(agentPath)) {
            try {
                if (Files.size(agentPath) == bytes.length) {
                    return agentPath;
                }
            } catch (IOException e) {
                LOG.warning("Failed to check size of " + agentPath, e);
            }
        }

        Files.createDirectories(agentPath.getParent());
        FileUtils.saveSafely(agentPath, output -> output.write(bytes));
        return agentPath;

View on GitHub (pinned to 24702dc5a0)