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

  1. Check the integer matches one of NodeState's declared thrift values before calling valueOf
  2. Catch IllegalArgumentException and handle unknown values explicitly
  3. Align cluster versions so both sides share the same NodeState enum definition
  4. 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

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


AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04). Data as JSON: /api/errors/0e26ffea1d92f826. Report an issue: GitHub.