redis/redis-py · error · RedisError

Invalid option for CLUSTER FAILOVER command: {option}

Error message

Invalid option for CLUSTER FAILOVER command: {option}

What it means

Raised in RedisClusterCommands.cluster_failover (redis/commands/cluster.py:644) when an option is supplied whose uppercase form is neither 'FORCE' nor 'TAKEOVER'. CLUSTER FAILOVER only accepts those two optional modifiers (plus no option at all); any other string is rejected before the command is sent.

Source

Thrown at redis/commands/cluster.py:644

        target_node: "TargetNodesT",
        option: str | None = None,
    ) -> Awaitable[bool]: ...

    def cluster_failover(
        self, target_node: "TargetNodesT", option: str | None = None
    ) -> bool | Awaitable[bool]:
        """
        Forces a slave to perform a manual failover of its master
        Sends to specified node

        :target_node: 'ClusterNode'
            The node to execute the command on

        For more information see https://redis.io/commands/cluster-failover
        """
        if option:
            if option.upper() not in ["FORCE", "TAKEOVER"]:
                raise RedisError(
                    f"Invalid option for CLUSTER FAILOVER command: {option}"
                )
            else:
                return self.execute_command(
                    "CLUSTER FAILOVER", option, target_nodes=target_node
                )
        else:
            return self.execute_command("CLUSTER FAILOVER", target_nodes=target_node)

    @overload
    def cluster_info(
        self: SyncClientProtocol, target_nodes: "TargetNodesT" | None = None
    ) -> dict[str, str]: ...

    @overload
    def cluster_info(
        self: AsyncClientProtocol, target_nodes: "TargetNodesT" | None = None
    ) -> Awaitable[dict[str, str]]: ...

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass one of the allowed values: option=None (plain failover), option='FORCE', or option='TAKEOVER' (case-insensitive).
  2. Validate/normalize user-supplied options before calling: opt = option.upper() if option else None; assert opt in (None,'FORCE','TAKEOVER').
  3. Strip whitespace and reject unknown values upstream so invalid input never reaches the client.

Example fix

# before
rc.cluster_failover(target_node=replica, option='TAKE_OVER')  # raises

# after
rc.cluster_failover(target_node=replica, option='TAKEOVER')
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED_FAILOVER_OPTIONS = {None, 'FORCE', 'TAKEOVER'}

def normalize_failover_option(option):
    if option is None:
        return None
    opt = option.strip().upper()
    if opt not in ALLOWED_FAILOVER_OPTIONS:
        raise ValueError(f'CLUSTER FAILOVER option must be FORCE or TAKEOVER, got {option!r}')
    return opt

def safe_failover(client, target_node, option=None):
    return client.cluster_failover(
        target_node=target_node, option=normalize_failover_option(option)
    )

Try / catch

from redis.exceptions import RedisError

try:
    rc.cluster_failover(target_node=replica, option=user_opt)
except RedisError as e:
    if 'Invalid option for CLUSTER FAILOVER' in str(e):
        opt = user_opt.strip().upper() if user_opt else None
        if opt in ('FORCE', 'TAKEOVER'):
            rc.cluster_failover(target_node=replica, option=opt)
        else:
            raise
    else:
        raise

Prevention

When it happens

Trigger: Calling rc.cluster_failover(target_node=replica, option='ABORT'), option='force-takeover', option='SYNC', or any value not equal (case-insensitive) to FORCE or TAKEOVER. Typos like 'FORCE ' (trailing space) or 'TAKE_OVER' also trip it.

Common situations: Guessing option names from memory. Passing user input or config values without validation. Copying examples from sources that invented option names. Localized/uppercased values with unexpected whitespace.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/b22ab57ae64e6738.json. Report an issue: GitHub.