Grasscutters/Grasscutter · error · IOException
Invalid Enum definition -
Error message
Invalid Enum definition -
What it means
The enum TypeAdapter factory maps enum constants by name string and by integer ordinal-as-string; any other JSON token (object, array, boolean, null) cannot represent an enum and throws this IOException. Note the returned map.get(...) may itself yield null for unknown names/numbers, but non-scalar tokens hit this throw directly.
Source
Thrown at src/main/java/emu/grasscutter/utils/JsonAdapters.java:194
for (var constant : enumConstants) {
var accessible = f.canAccess(constant);
f.setAccessible(true);
map.put(String.valueOf(f.getInt(constant)), constant);
f.setAccessible(accessible);
}
} catch (IllegalAccessException e) {
// System.out.println("Failed to access enum id field.");
}
break;
}
}
return new TypeAdapter<>() {
public T read(JsonReader reader) throws IOException {
return switch (reader.peek()) {
case STRING -> map.get(reader.nextString());
case NUMBER -> map.get(String.valueOf(reader.nextInt()));
default -> throw new IOException("Invalid Enum definition - " + reader.peek().name());
};
}
public void write(JsonWriter writer, T value) throws IOException {
writer.value(value.toString());
}
};
}
}
}
View on GitHub (pinned to f373827a83)
Solutions
- Change the JSON value to the enum's name string (e.g. "OPEN") or its integer form
- Replace JSON null with a valid enum name, or declare the field nullable/skip it
- Preprocess input JSON to unwrap nested enum objects before Gson parsing
- Check which enum and file failed (message appends reader.peek().name()) and fix that value
Example fix
// before
"openState": {"id": 1}
// after
"openState": 1 Defensive patterns
Strategy: validation
Validate before calling
boolean isValidEnumValue(Class<? extends Enum<?>> type, com.google.gson.JsonElement el) {
if (el == null || !el.isJsonPrimitive()) return false;
String s = el.getAsString();
for (Enum<?> c : type.getEnumConstants())
if (c.name().equals(s) || String.valueOf(c.ordinal()).equals(s)) return true;
return false;
} Type guard
boolean isEnumToken(com.google.gson.JsonElement el) {
return el != null && el.isJsonPrimitive()
&& (el.getAsJsonPrimitive().isString() || el.getAsJsonPrimitive().isNumber());
} Try / catch
try {
MyEnum v = gson.fromJson(el, MyEnum.class);
} catch (IOException e) {
logger.warn("Bad enum token: {}", e.getMessage());
} Prevention
- Write enums as name strings or plain integers in JSON
- Never put null or objects in enum-typed fields
- Validate enum fields against Enum.valueOf before parsing
- Keep configs generated by the same schema that reads them
When it happens
Trigger: Deserializing an enum-typed field where the JSON value is an object, array, boolean, or null token; e.g. "openState": {"value":1} or "openState": [1] instead of "openState": 1 or "openState": "OPEN".
Common situations: Configs exported with wrapped enum objects by other frameworks; null enum values in JSON where the field is non-nullable in Java; hand-edited resources using wrong value types.
Related errors
- Invalid DynamicFloat definition -
- Invalid IntList definition -
- Invalid GridPosition definition -
- Invalid field in Position definition -
- Invalid Position definition -
AI-assisted analysis of Grasscutters/Grasscutter@f373827a83 (2026-09-03).
Data as JSON: /api/errors/9ed6d8bf44e0fd54.
Report an issue: GitHub.