HMCL-dev/HMCL · error · IllegalArgumentException
Missing game manifest
Error message
Missing game manifest
What it means
Instances.installFromJson reads a GameInstanceManifest JSON file to install a Minecraft game instance. If JsonUtils.fromJsonFile returns null (empty or whitespace-only file that parses to no value), it throws IllegalArgumentException('Missing game manifest'); the method catches it, logs a warning, shows a 'malformed JSON' dialog, and aborts the install.
Solutions
- Ensure the file contains a complete GameInstanceManifest JSON object (non-empty, with formatVersion etc.).
- Check the file size on disk — recreate/re-download the manifest if it is 0 bytes.
- Export a fresh manifest from the source instance before importing.
- Pre-validate with JsonUtils.fromJsonFile yourself and show a clearer error than 'malformed json'.
Example fix
// before: importing an empty file silently fails
Instances.installFromJson(repo, Path.of("empty.json"));
// after: guard first
String content = Files.readString(file);
if (content.isBlank()) throw new IllegalArgumentException("Manifest file is empty: " + file);
Instances.installFromJson(repo, file); Defensive patterns
Strategy: validation
Validate before calling
// validate manifest file before calling installFromJson
static void requireInstallableManifest(Path file) throws IOException {
if (!Files.isRegularFile(file) || Files.size(file) == 0)
throw new IllegalArgumentException("manifest file missing or empty: " + file);
GameInstanceManifest m = JsonUtils.fromJsonFile(file, GameInstanceManifest.class);
if (m == null) throw new IllegalArgumentException("manifest is empty/null");
} Try / catch
try {
Instances.installFromJson(repository, file);
} catch (IllegalArgumentException e) {
// installFromJson shows its own dialog and returns; only reached for pre-validation failures
Controllers.dialog("Manifest file is empty or unreadable", i18n("message.error"),
MessageDialogPane.MessageType.ERROR);
} Prevention
- Check file size > 0 before importing a manifest.
- Export manifests from a working instance rather than hand-writing them.
- Verify JSON parses with JsonUtils.fromJsonFile before invoking the installer.
- Log the file path and content snippet on failure for diagnosis.
When it happens
Trigger: Calling installFromJson(repository, path) with a file that is empty, contains only whitespace/null JSON, or cannot be deserialized into a non-null GameInstanceManifest.
Common situations: Selecting a zero-byte or placeholder file in the import-installer UI; a download of the manifest was interrupted leaving an empty file; pointing the installer at a non-manifest JSON file.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- Game manifest inherits from another manifest
- Missing protected payload member: nonce
- Protected payload is not a
- "Mod " + modFile + " `mcmod.info` is malformed"
- "Unexpected first token: " + firstToken
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/13a3612407830a02.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/ui/instances/Instances.java:179
}, instanceId.toString(),
new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidInstanceId),
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);View on GitHub (pinned to 24702dc5a0)