HMCL-dev/HMCL · error · JsonParseException
Game directory ID cannot be nil
Error message
Game directory ID cannot be nil
What it means
GameDirectory's deserializer rejects entries whose "id" decodes to the special GameDirectoryID.NIL sentinel (e.g. an all-zero/placeholder UUID). NIL is reserved for internal/default use, so a persisted directory with NIL has no meaningful identity and JsonParseException("Game directory ID cannot be nil") is thrown. Note the whole element not being an object yields null earlier — this error fires only for object entries with a NIL id.
Solutions
- Replace the nil/zero ID with a fresh unique ID (e.g. a random UUID) in settings.json
- Re-add the game directory through the HMCL UI, which generates a valid ID
- Find the code path that saved GameDirectoryID.NIL (uninitialized ID property) and ensure a real ID is assigned before persistence
- Delete the offending entry and let HMCL recreate it
Example fix
// before
{ "id": "00000000-0000-0000-0000-000000000000", "path": "D:/minecraft" }
// after
{ "id": "7c9e6679-7425-40de-944b-e07fc1f90ae7", "path": "D:/minecraft" } Defensive patterns
Strategy: validation
Validate before calling
JsonObject entry = ...;
String id = entry.getAsJsonPrimitive("id").getAsString();
if (id.matches("^0{8}(-0{4}){3}-0{12}$"))
throw new IOException("Game directory has nil id; assign a real unique id"); Type guard
static boolean hasRealId(JsonObject entry) {
JsonElement id = entry.get("id");
return id != null && id.isJsonPrimitive()
&& !"00000000-0000-0000-0000-000000000000".equals(id.getAsString());
} Try / catch
try {
GameDirectory d = gson.fromJson(entry, GameDirectory.class);
} catch (JsonParseException e) {
if (e.getMessage().contains("nil")) {
LOGGER.warning("Preset/directory had placeholder id; regenerating");
// replace id with a fresh UUID and retry
}
} Prevention
- Assign real unique IDs at creation time before persisting
- Never serialize sentinel/nil IDs to config files
- Regenerate placeholder IDs left by templates or tooling
- Validate ids (non-nil, unique) before saving settings
When it happens
Trigger: Deserializing a settings JSON entry where the "id" field deserializes into GameDirectoryID.NIL — e.g. an id serialized as all zeros/empty placeholder because the ID was never initialized before saving.
Common situations: A tool or old build that wrote a default/zero UUID for new directories; config generated by templating that left the id as a placeholder; saving before the ID property was initialized due to a version bug.
Related errors
- Preset ID cannot be nil
- Game directory ID cannot be null
- Game directory path cannot be null
- json.toString()
- json.toString()
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/51b3ceaf8825eb43.
Report an issue: GitHub.
Appendix: source
Thrown at HMCL/src/main/java/org/jackhuang/hmcl/setting/GameDirectory.java:195
}
}
jsonObject.add("path", context.serialize(src.getPath(), PortablePath.class));
if (src.getLegacyGameSettings() != null) {
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)