HMCL-dev/HMCL · error · JsonParseException
Game directory path cannot be null
Error message
Game directory path cannot be null
What it means
GameDirectory's deserializer requires a non-null "path" field. After validating the id, it deserializes obj.get("path") into PortablePath; if absent or unresolvable, it throws JsonParseException("Game directory path cannot be null") since a game directory without a filesystem location is meaningless.
Solutions
- Add the missing "path" field with a valid filesystem path to the entry in settings.json
- Check the key spelling/casing — it must be exactly "path" and must match PortablePath's expected format
- Re-add the game directory via the HMCL UI instead of hand-editing the settings file
- Remove the malformed entry and restore settings.json from a backup
Example fix
// before
{ "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7" }
// after
{ "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "path": "D:/minecraft" } Defensive patterns
Strategy: validation
Validate before calling
JsonObject entry = ...;
if (!entry.has("path") || entry.get("path").isJsonNull())
throw new IOException("Game directory entry missing path"); Type guard
static boolean hasDirectoryPath(JsonObject entry) {
JsonElement p = entry.get("path");
return p != null && !p.isJsonNull();
} Try / catch
try {
GameDirectory d = gson.fromJson(entry, GameDirectory.class);
} catch (JsonParseException e) {
LOGGER.warning("Malformed game directory (missing path?): " + e.getMessage());
// drop or repair the entry before loading settings
} Prevention
- Use exact key names ("id", "path", "name") matching the deserializer
- Prefer the HMCL UI over manual settings.json edits
- Back up settings.json before editing or syncing across machines
- Validate entries against the schema when migrating configs between HMCL versions
When it happens
Trigger: Deserializing a settings JSON game-directory object that has a valid id but no "path" member, or a "path" value that PortablePath's adapter cannot decode into a non-null PortablePath.
Common situations: Hand-edited settings.json where path was removed or misspelled (e.g. "dir" instead of "path"); entries produced by a different HMCL fork using different keys; truncated settings file cutting off the path field.
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
- Game directory ID cannot be null
- Account private data is not an object
- Game directory ID cannot be nil
- Preset ID cannot be nil
- json.toString()
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/9f166714544881be.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/setting/GameDirectory.java:199
jsonObject.add("legacyGameSettings", context.serialize(src.getLegacyGameSettings(), GameSettingsPresetID.class));
}
return jsonObject;
}
/// Deserializes a game directory from JSON.
@Override
public @Nullable GameDirectory deserialize(@Nullable JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (!(json instanceof JsonObject obj)) return null;
GameDirectoryID id = context.deserialize(obj.get("id"), GameDirectoryID.class);
if (id == null) {
throw new JsonParseException("Game directory ID cannot be null");
} else if (GameDirectoryID.NIL.equals(id)) {
throw new JsonParseException("Game directory ID cannot be nil");
}
PortablePath path = context.deserialize(obj.get("path"), PortablePath.class);
if (path == null) {
throw new JsonParseException("Game directory path cannot be null");
}
@Nullable LocalizedText name = context.deserialize(obj.get("name"), LocalizedText.class);
return new GameDirectory(id,
name,
path,
context.deserialize(obj.get("legacyGameSettings"), GameSettingsPresetID.class));
}
}
}
View on GitHub (pinned to 24702dc5a0)