redis/redis-py · error · DataError

CLIENT KILL type must be one of

Error message

CLIENT KILL type must be one of {client_types!r}

What it means

Raised by Redis.client_kill() when the `_type` argument is supplied but is not one of the allowed client types: 'normal', 'master', 'slave', 'replica', 'pubsub' (case-insensitive via str(_type).lower()). The library validates before building the CLIENT KILL argument list. Other filter fields (_id, addr, laddr, user, maxage, skipme) are not subject to this specific check.

Solutions

  1. Use one of 'normal', 'master', 'slave', 'replica', 'pubsub' for _type.
  2. Prefer 'replica' over 'slave' for forward compatibility (both are accepted).
  3. If you have a custom enum, map it to these canonical names before calling.

Example fix

# before
client.client_kill(_type='subscriber')
# after
client.client_kill(_type='pubsub')
Defensive patterns

Strategy: validation

Validate before calling

VALID_CLIENT_KILL_TYPES = {'normal', 'master', 'slave', 'replica', 'pubsub'}
def safe_client_kill(client, _type=None, **kw):
    if _type is not None and str(_type).lower() not in VALID_CLIENT_KILL_TYPES:
        raise ValueError(f'_type must be one of {VALID_CLIENT_KILL_TYPES}, got {_type!r}')
    return client.client_kill(_type=_type, **kw)

Type guard

def is_valid_client_kill_type(_type) -> bool:
    return _type is None or (isinstance(_type, str) and _type.lower() in {'normal', 'master', 'slave', 'replica', 'pubsub'})

Try / catch

from redis.exceptions import DataError
try:
    client.client_kill(_type=_type)
except DataError as e:
    if 'CLIENT KILL type' in str(e):
        # map or reject upstream; do not blindly retry
        raise ValueError(f'invalid client kill type: {_type}') from e
    raise

Prevention

When it happens

Trigger: Calling client.client_kill(_type='publisher') (invalid), _type='PUBSUB' (valid, case-insensitive), _type='slave' (valid), or _type='replica' (valid). A misspelled or unsupported type like 'pub' or 'subscriber' triggers the error.

Common situations: Mismatched terminology between your app ('publisher','subscriber') and Redis client types; passing a numeric type code instead of the string name; case-sensitivity assumptions (the check lowercases, so casing is fine, but spelling must match).

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/01ea4439cd2150bc. Report an issue: GitHub.

Appendix: source

Thrown at redis/commands/core.py:778

    ) -> int | Awaitable[int]:
        """
        Disconnects client(s) using a variety of filter options
        :param _id: Kills a client by its unique ID field
        :param _type: Kills a client by type where type is one of 'normal',
        'master', 'slave', 'replica' or 'pubsub'
        :param addr: Kills a client by its 'address:port'
        :param skipme: If True, then the client calling the command
        will not get killed even if it is identified by one of the filter
        options. If skipme is not provided, the server defaults to skipme=True
        :param laddr: Kills a client by its 'local (bind) address:port'
        :param user: Kills a client for a specific user name
        :param maxage: Kills clients that are older than the specified age in seconds
        """
        args = []
        if _type is not None:
            client_types = ("normal", "master", "slave", "replica", "pubsub")
            if str(_type).lower() not in client_types:
                raise DataError(f"CLIENT KILL type must be one of {client_types!r}")
            args.extend((b"TYPE", _type))
        if skipme is not None:
            if not isinstance(skipme, bool):
                raise DataError("CLIENT KILL skipme must be a bool")
            if skipme:
                args.extend((b"SKIPME", b"YES"))
            else:
                args.extend((b"SKIPME", b"NO"))
        if _id is not None:
            args.extend((b"ID", _id))
        if addr is not None:
            args.extend((b"ADDR", addr))
        if laddr is not None:
            args.extend((b"LADDR", laddr))
        if user is not None:
            args.extend((b"USER", user))
        if maxage is not None:
            args.extend((b"MAXAGE", maxage))

View on GitHub (pinned to 6a6b581b48)