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
- Supply at least one filter, e.g. r.client_kill(_id=client_id) or r.client_kill(addr="1.2.3.4:1234")
- To kill the current connection, use r.client_id() to obtain the id then r.client_kill(_id=that_id)
- 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
- Always target a concrete client (id/addr) or a type when calling client_kill.
- Build the filter dict from non-None values and check it is non-empty before calling.
- Avoid 'kill everything' patterns; the protocol does not support them.
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
- client_id must be a list
- CLIENT KILL skipme must be a bool
- CLIENT LIST _type must be one of
- CLIENT PAUSE timeout must be an integer
- CLIENT REPLY must be one of
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 currentView on GitHub (pinned to 6a6b581b48)