HMCL-dev/HMCL · error · IllegalArgumentException

Game manifest inherits from another manifest

Error message

Game manifest inherits from another manifest

What it means

GameInstanceManifest supports inheritance via an inheritsFrom field; installFromJson refuses manifests that declare inheritance because the installer cannot resolve the parent manifest. It throws IllegalArgumentException('Game manifest inherits from another manifest'), which installFromJson catches, logs, shows a 'malformed JSON' dialog, and returns without installing.

Solutions

  1. Remove the inheritsFrom field and inline/merge any parent manifest fields before importing.
  2. Export the full self-contained instance manifest instead of a child manifest.
  3. If the parent exists, import the parent manifest first or use the full-instance export flow.
  4. Strip the field programmatically before calling installFromJson if inheritance is not needed.

Example fix

// before: child manifest rejected
Instances.installFromJson(repo, Path.of("child-manifest.json")); // inheritsFrom != null
// after: inline the parent, then import
GameInstanceManifest m = JsonUtils.fromJsonFile(file, GameInstanceManifest.class);
GameInstanceManifest merged = mergeWithParent(m);
Files.write(file, JsonUtils.toJson(merged).getBytes());
Instances.installFromJson(repo, file);
Defensive patterns

Strategy: validation

Validate before calling

// reject or resolve inheritance before install
GameInstanceManifest m = JsonUtils.fromJsonFile(file, GameInstanceManifest.class);
if (m != null && m.inheritsFrom() != null) {
  Path parent = resolveParentManifest(m.inheritsFrom());
  if (parent == null)
    throw new IllegalArgumentException("inheritsFrom '" + m.inheritsFrom() + "' cannot be resolved; export a self-contained manifest");
}

Try / catch

try {
  Instances.installFromJson(repository, file);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().contains("inherits")) {
    Controllers.dialog("This manifest inherits from another instance; import a full manifest instead",
        i18n("message.error"), MessageDialogPane.MessageType.ERROR);
  }
}

Prevention

When it happens

Trigger: Importing a manifest JSON whose inheritsFrom property is non-null — typically an exported/subset manifest that references a parent instance, fed to Instances.installFromJson.

Common situations: Hand-editing an exported manifest and leaving inheritsFrom in place; exporting only part of an instance chain; using manifests generated for a different installer that supports inheritance.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/Instances.java:181

            new Validator(i18n("install.new_game.already_exists"), newVersionName -> !repository.instanceIdConflicts(newVersionName) || newVersionName.equals(instanceId.toString())));
    }

    public static void exportInstance(HMCLGameInstance gameInstance) {
        Controllers.getDecorator().startWizard(new ExportWizardProvider(gameInstance), i18n("modpack.wizard"));
    }

    public static void openFolder(HMCLGameInstance gameInstance) {
        FXUtils.openFolder(gameInstance.getRunDirectory());
    }

    public static void installFromJson(HMCLGameRepository repository, Path file) {
        GameInstanceManifest manifest;
        try {
            manifest = JsonUtils.fromJsonFile(file, GameInstanceManifest.class);
            if (manifest == null)
                throw new IllegalArgumentException("Missing game manifest");
            if (manifest.inheritsFrom() != null)
                throw new IllegalArgumentException("Game manifest inherits from another manifest");
        } catch (Exception e) {
            LOG.warning("Failed to read game manifest from " + file, e);
            Controllers.dialog(i18n("install.new_game.malformed_json"), i18n("message.error"), MessageDialogPane.MessageType.ERROR);
            return;
        }

        Controllers.prompt(i18n("instance.manage.duplicate.prompt"), (result, handler) -> {
            handler.resolve();

            GameInstanceID instanceId = new GameInstanceID(result);

            DefaultDependencyManager dependencyManager = repository.getDependency();
            GameInstanceManifest newManifest = manifest.withId(instanceId).withJar(instanceId);
            GameDownloadTask gameDownloadTask = new GameDownloadTask(
                    dependencyManager,
                    newManifest);
            AtomicReference<GameRepositoryDraft> activeDraft = new AtomicReference<>();

View on GitHub (pinned to 24702dc5a0)