HMCL-dev/HMCL · error · IllegalArgumentException

Instance

Error message

Instance 

What it means

Thrown by the ModrinthInstallTask constructor when an update is requested (updateTarget != null) but the target instance directory has no modpack configuration file, meaning the instance was not originally installed as a Modrinth modpack. The task only supports updating instances it can re-resolve via a stored Modrinth ModpackConfiguration.

Solutions

  1. Install the instance as a Modrinth modpack first so the modpack configuration file is created, then update
  2. Pass null updateTarget to perform a fresh install instead of an update
  3. Verify the instanceId points at an existing Modrinth-managed instance in the game repository

Example fix

// before
new ModrinthInstallTask(dependencyManager, someNonModrinthInstance, modpack, null); // updateTarget set on non-modrinth instance
// after
new ModrinthInstallTask(dependencyManager, null, modpack, null); // fresh install
Defensive patterns

Strategy: validation

Validate before calling

Path json = repository.getLayout().getModpackConfigurationFile(instanceId);
if (updateTarget != null && Files.notExists(json)) throw new IllegalStateException(instanceId + " is not a Modrinth modpack");

Try / catch

try { new ModrinthInstallTask(...).start(); } catch (IllegalArgumentException e) { /* fall back to fresh install */ }

Prevention

When it happens

Trigger: Calling new ModrinthInstallTask(...) with a non-null updateTarget for an instanceId whose modpackConfiguration JSON file does not exist under the instance root.

Common situations: User selects 'update' on a manually created instance or an instance imported from another launcher (vanilla, CurseForge, MultiMC), then HMCL tries to treat it as a Modrinth pack.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/modpack/modrinth/ModrinthInstallTask.java:144

            Path zipFile,
            Modpack modpack,
            ModrinthManifest manifest,
            GameInstanceID instanceId,
            @Nullable DefaultGameInstance updateTarget,
            @Nullable String iconUrl) {
        this.dependencyManager = dependencyManager;
        this.zipFile = zipFile;
        this.modpack = modpack;
        this.manifest = manifest;
        this.instanceId = instanceId;
        this.updateTarget = updateTarget;
        this.iconUrl = iconUrl;
        this.repository = dependencyManager.getGameRepository();
        this.run = repository.getLayout().getInstanceRoot(instanceId);

        Path json = repository.getLayout().getModpackConfigurationFile(instanceId);
        if (this.updateTarget != null && Files.notExists(json))
            throw new IllegalArgumentException("Instance " + instanceId + " is not a Modrinth modpack. Cannot update this instance.");

        @Nullable ModpackConfiguration<ModrinthManifest> config = null;
        try {
            if (this.updateTarget != null && Files.exists(json)) {
                config = JsonUtils.fromJsonFile(json, ModpackConfiguration.typeOf(ModrinthManifest.class));

                if (config == null || !ModrinthModpackProvider.INSTANCE.getName().equals(config.getType()))
                    throw new IllegalArgumentException("Instance " + instanceId + " is not a Modrinth modpack. Cannot update this instance.");
            }
        } catch (JsonParseException | IOException ignore) {
        }
        this.config = config;

        onDone().register(event -> {
            @Nullable Exception ex = event.getTask().getException();
            if (this.updateTarget == null && event.isFailed()) {
                if (!(ex instanceof ModpackCompletionException)) {
                    repository.removeInstanceFromDisk(instanceId);

View on GitHub (pinned to 24702dc5a0)