{"record":{"id":"bc47f76a390fedd6","repo":"redis/redis-py","slug":"invalid-slot-state-state","errorCode":null,"errorMessage":"Invalid slot state: {state}","messagePattern":"Invalid slot state: (.+?)","errorType":"exception","errorClass":"RedisError","httpStatus":null,"severity":"error","filePath":"redis/commands/cluster.py","lineNumber":890,"sourceCode":"    def cluster_setslot(\n        self, target_node: \"TargetNodesT\", node_id: str, slot_id: int, state: str\n    ) -> bool | Awaitable[bool]:\n        \"\"\"\n        Bind an hash slot to a specific node\n\n        :target_node: 'ClusterNode'\n            The node to execute the command on\n\n        For more information see https://redis.io/commands/cluster-setslot\n        \"\"\"\n        if state.upper() in (\"IMPORTING\", \"NODE\", \"MIGRATING\"):\n            return self.execute_command(\n                \"CLUSTER SETSLOT\", slot_id, state, node_id, target_nodes=target_node\n            )\n        elif state.upper() == \"STABLE\":\n            raise RedisError('For \"stable\" state please use cluster_setslot_stable')\n        else:\n            raise RedisError(f\"Invalid slot state: {state}\")\n\n    @overload\n    def cluster_setslot_stable(self: SyncClientProtocol, slot_id: int) -> bool: ...\n\n    @overload\n    def cluster_setslot_stable(\n        self: AsyncClientProtocol, slot_id: int\n    ) -> Awaitable[bool]: ...\n\n    def cluster_setslot_stable(self, slot_id: int) -> bool | Awaitable[bool]:\n        \"\"\"\n        Clears migrating / importing state from the slot.\n        It determines by it self what node the slot is in and sends it there.\n\n        For more information see https://redis.io/commands/cluster-setslot\n        \"\"\"\n        return self.execute_command(\"CLUSTER SETSLOT\", slot_id, \"STABLE\")\n","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/cluster.py#L872-L908","documentation":"Raised by RedisCluster.cluster_setslot() when the `state` argument is not one of the accepted values. The method only accepts 'IMPORTING', 'NODE', 'MIGRATING' (which it forwards to CLUSTER SETSLOT) and treats 'STABLE' specially by redirecting to cluster_setslot_stable(). Any other value is rejected client-side before any command is sent to Redis. This is an input-validation guard, not a server error.","triggerScenarios":"Calling client.cluster_setslot(target_node, node_id, slot_id, state) with a `state` string outside {'IMPORTING','NODE','MIGRATING','STABLE'} (case-insensitive). Examples: state='MIGRATE' (typo), state='MOVING', state='IMPORT', state='', or passing an int/None as state (AttributeError on .upper() aside, the branch falls through to the else).","commonSituations":"Migrating hash slots between cluster nodes manually; misspelling a slot state constant; using a value valid in redis-cli but not exposed by this client wrapper; copy-pasting from Redis docs that list states the client intentionally funnels through a separate method.","solutions":["Use one of 'IMPORTING', 'NODE', or 'MIGRATING' as the state argument.","If you meant to clear a slot's migration state, call cluster_setslot_stable(slot_id) instead of cluster_setslot(..., state='STABLE').","Check the spelling and case of the state string against the accepted set."],"exampleFix":"# before\nclient.cluster_setslot(node, node_id, slot_id, state='MIGRATE')\n# after\nclient.cluster_setslot(node, node_id, slot_id, state='MIGRATING')\n# or for clearing state:\nclient.cluster_setslot_stable(slot_id)","handlingStrategy":"validation","validationCode":"VALID_SLOT_STATES = {'IMPORTING', 'NODE', 'MIGRATING'}\ndef set_slot(node, node_id, slot_id, state):\n    s = state.upper()\n    if s == 'STABLE':\n        client.cluster_setslot_stable(slot_id)\n    elif s in VALID_SLOT_STATES:\n        client.cluster_setslot(node, node_id, slot_id, state)\n    else:\n        raise ValueError(f'state must be one of {VALID_SLOT_STATES | {\"STABLE\"}}, got {state!r}')","typeGuard":"def is_valid_slot_state(state: str) -> bool:\n    return isinstance(state, str) and state.upper() in {'IMPORTING', 'NODE', 'MIGRATING', 'STABLE'}","tryCatchPattern":"from redis.exceptions import RedisError\ntry:\n    client.cluster_setslot(node, node_id, slot_id, state)\nexcept RedisError as e:\n    if 'Invalid slot state' in str(e):\n        # fix state and retry or surface config error\n        ...\n    raise","preventionTips":["Centralize slot-migration logic behind a helper that validates the state enum.","Treat 'STABLE' as a separate code path that calls cluster_setslot_stable().","Add a unit test covering each accepted state plus one rejected value."],"tags":["redis-cluster","validation","cluster-setslot","input-validation"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}