{"record":{"id":"0e26ffea1d92f826","repo":"prestodb/presto","slug":"invalid-nodestate-value","errorCode":null,"errorMessage":"Invalid NodeState value: ","messagePattern":"Invalid NodeState value: ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"presto-spi/src/main/java/com/facebook/presto/spi/NodeState.java","lineNumber":45,"sourceCode":"\n    NodeState(int value)\n    {\n        this.value = value;\n    }\n\n    /**\n     * Recover NodeState from the ordinal.\n     * In general, ThriftEnum is the right annotation to use.\n     * But given the class is in SPI, use the following workaround.\n     */\n    public static NodeState valueOf(int value)\n    {\n        for (NodeState nodeState : values()) {\n            if (nodeState.getValue() == value) {\n                return nodeState;\n            }\n        }\n        throw new IllegalArgumentException(\"Invalid NodeState value: \" + value);\n    }\n\n    // the value will be used for SerDe like thrift\n    @ThriftEnumValue\n    public int getValue()\n    {\n        return value;\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":55,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-spi/src/main/java/com/facebook/presto/spi/NodeState.java#L27-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nNodeState state = NodeState.valueOf(rawValue); // throws for unknown values\n// after\nNodeState state;\ntry {\n    state = NodeState.valueOf(rawValue);\n} catch (IllegalArgumentException e) {\n    state = NodeState.ACTIVE; // or log & treat as unknown\n    log.warn(\"Unknown NodeState value %d\", rawValue);\n}","handlingStrategy":"type-guard","validationCode":"boolean isValidNodeState(int value) {\n    for (NodeState s : NodeState.values()) {\n        if (s.getValue() == value) return true;\n    }\n    return false;\n}","typeGuard":"NodeState asNodeState(int value) {\n    return isValidNodeState(value) ? NodeState.valueOf(value) : null;\n}","tryCatchPattern":"try {\n    state = NodeState.valueOf(rawValue);\n} catch (IllegalArgumentException e) {\n    log.warn(\"Unknown NodeState value: %d\", rawValue);\n    state = null; // handle unknown explicitly\n}","preventionTips":["Round-trip test enum SerDe in CI","Keep NodeState enum definitions identical across cluster versions","Reject unknown thrift values at deserialization boundaries with logging"],"tags":["spi","enum","serialization","thrift","illegal-argument"],"backgroundTag":"invalid-enum-value","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}