prestodb/presto · error · IllegalArgumentException
Invalid NodeState value:
Error message
Invalid NodeState value:
What it means
NodeState is a Thrift-serialized enum; its static valueOf(int) maps a raw numeric value back to the enum constant by scanning values(). If no constant has a matching thrift value the integer is not a legitimate NodeState wire value, so the method throws IllegalArgumentException. This guards against corrupt or newer-protocol payloads containing unknown enum codes.
Source
Thrown at presto-spi/src/main/java/com/facebook/presto/spi/NodeState.java:45
NodeState(int value)
{
this.value = value;
}
/**
* Recover NodeState from the ordinal.
* In general, ThriftEnum is the right annotation to use.
* But given the class is in SPI, use the following workaround.
*/
public static NodeState valueOf(int value)
{
for (NodeState nodeState : values()) {
if (nodeState.getValue() == value) {
return nodeState;
}
}
throw new IllegalArgumentException("Invalid NodeState value: " + value);
}
// the value will be used for SerDe like thrift
@ThriftEnumValue
public int getValue()
{
return value;
}
}
View on GitHub (pinned to 55bb57d202)
Solutions
- Check the integer matches one of NodeState's declared thrift values before calling valueOf
- Catch IllegalArgumentException and handle unknown values explicitly
- Align cluster versions so both sides share the same NodeState enum definition
- Inspect the payload/source of the integer — it likely came from corrupt or foreign serialization
Example fix
// before
NodeState state = NodeState.valueOf(rawValue); // throws for unknown values
// after
NodeState state;
try {
state = NodeState.valueOf(rawValue);
} catch (IllegalArgumentException e) {
state = NodeState.ACTIVE; // or log & treat as unknown
log.warn("Unknown NodeState value %d", rawValue);
} Defensive patterns
Strategy: type-guard
Validate before calling
boolean isValidNodeState(int value) {
for (NodeState s : NodeState.values()) {
if (s.getValue() == value) return true;
}
return false;
} Type guard
NodeState asNodeState(int value) {
return isValidNodeState(value) ? NodeState.valueOf(value) : null;
} Try / catch
try {
state = NodeState.valueOf(rawValue);
} catch (IllegalArgumentException e) {
log.warn("Unknown NodeState value: %d", rawValue);
state = null; // handle unknown explicitly
} Prevention
- Round-trip test enum SerDe in CI
- Keep NodeState enum definitions identical across cluster versions
- Reject unknown thrift values at deserialization boundaries with logging
When it happens
Trigger: Calling NodeState.valueOf(int) with an integer that is not one of the declared @ThriftEnumValue constants — e.g. an out-of-range id from a thrift/serde payload, a byte/short cast wrong, or a value added in a newer version being read by older code.
Common situations: Cross-version cluster communication where a newer coordinator sends a NodeState the older node doesn't know; corrupted deserialized state; ad-hoc scripts guessing enum codes; accidental off-by-one when hand-building thrift structs.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- INVALID_ARGUMENTS
- INVALID_ARGUMENTS
- partitionHandle must be NOT_PARTITIONED
- SchemaTableName should have exactly 2 parts
- value must be > 0, found:
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/0e26ffea1d92f826.
Report an issue: GitHub.