HMCL-dev/HMCL · error · IOException

Missing hmcl.lwjgl-unsafe-agent.version attribute

Error message

Missing hmcl.lwjgl-unsafe-agent.version attribute

What it means

Thrown when updating an instance whose existing modpack configuration JSON declares a different provider type than 'mcbbs'. The task only allows updates within the same modpack format, so an instance installed from e.g. a CurseForge or Modrinth pack cannot be updated as an Mcbbs pack.

Solutions

  1. Use the matching provider (e.g. Modrinth/CurseForge task) for the instance's original modpack type
  2. Pass updateTarget = null to reinstall as a new Mcbbs pack (overwrites)
  3. Check the modpack.cfg type field to confirm which pack format installed the instance
  4. Create a fresh instance and install the Mcbbs pack there
Defensive patterns

Strategy: validation

Validate before calling

ModpackConfiguration<?> config = JsonUtils.fromJsonFile(configFile, ModpackConfiguration.typeOf(Object.class));
if (config != null && !"mcbbs".equals(config.getType()))
    useProviderFor(config.getType());

Type guard

if (config != null && McbbsModpackProvider.INSTANCE.getName().equals(config.getType())) { /* safe */ }

Try / catch

try { task.execute(); } catch (IllegalArgumentException e) { /* route to provider matching config.getType() */ }

Prevention

When it happens

Trigger: new McbbsModpackLocalInstallTask(..., updateTarget=<non-null>) where the existing configuration file parses but config.getType() is not "mcbbs" (or config is null despite the file existing).

Common situations: Updating an instance that was originally installed from a CurseForge/Modrinth/other pack; the config file was overwritten by another launcher; wrong task/provider chosen for the instance.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

        super.appendJvmArgs(result);

        if (options.isAllowAutoAgent()
                && !options.isNoGeneratedJVMArgs()
                && !options.isNoGeneratedOptimizingJVMArgs()
                && NativePatcher.needPatchMemoryUtil(manifest, options.getJava().getParsedVersion())) {
            LOG.info("Attempting to patch game with lwjgl-unsafe-agent");
            try {
                result.add("-javaagent:" + extractLwjglUnsafeAgent());
            } catch (Exception e) {
                LOG.warning("Failed to extract lwjgl-unsafe-agent", e);
            }
        }
    }

    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();
        }

View on GitHub (pinned to 24702dc5a0)