redis/redis-py · error · DataError

CLIENT KILL ... ... must specify at least one filter

Error message

CLIENT KILL <filter> <value> ... ... <filter> <value> must specify at least one filter

What it means

Raised by client_kill() (redis/commands/core.py:798) when every filter argument (_type, skipme, _id, addr, laddr, user, maxage) is None, leaving the assembled args list empty. CLIENT KILL with no filters is meaningless at the protocol level, so the library refuses to send it. This is a redis.exceptions.DataError raised before any command is sent.

Solutions

  1. Supply at least one filter, e.g. r.client_kill(_id=client_id) or r.client_kill(addr="1.2.3.4:1234")
  2. To kill the current connection, use r.client_id() to obtain the id then r.client_kill(_id=that_id)
  3. To kill by type, pass _type="normal" (also accepted: master, replica, pubsub)

Example fix

# before
r.client_kill()
# after
r.client_kill(_id=r.client_id())
Defensive patterns

Strategy: validation

Validate before calling

filters = {"_id": _id, "addr": addr, "_type": _type, "user": user}
provided = {k: v for k, v in filters.items() if v is not None}
if not provided:
    raise ValueError("supply at least one CLIENT KILL filter")
r.client_kill(**provided)

Try / catch

from redis.exceptions import DataError
try:
    r.client_kill(**filters)
except DataError as e:
    if "at least one filter" in str(e):
        # nothing to kill; treat as no-op
        pass
    else:
        raise

Prevention

When it happens

Trigger: Calling r.client_kill() with no arguments, or r.client_kill(_id=None, addr=None) where all filters resolve to None. Because each filter is checked with 'is not None', passing an explicit None for every argument still triggers it.

Common situations: Calling client_kill() expecting it to kill all clients or the current client; or conditionally building filters that all evaluate to None at runtime (e.g. all config-driven filters happen to be unset).

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:798

        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))
        if not args:
            raise DataError(
                "CLIENT KILL <filter> <value> ... ... <filter> "
                "<value> must specify at least one filter"
            )
        return self.execute_command("CLIENT KILL", *args, **kwargs)

    @overload
    def client_info(self: SyncClientProtocol, **kwargs) -> dict[str, str | int]: ...

    @overload
    def client_info(
        self: AsyncClientProtocol, **kwargs
    ) -> Awaitable[dict[str, str | int]]: ...

    def client_info(
        self, **kwargs
    ) -> dict[str, str | int] | Awaitable[dict[str, str | int]]:
        """
        Returns information and statistics about the current

View on GitHub (pinned to 6a6b581b48)