redis/redis-py · error · DataError
XACKDEL ref_policy must be one of: KEEPREF, DELREF, ACKED
Error message
XACKDEL ref_policy must be one of: KEEPREF, DELREF, ACKED
What it means
Raised by xackdel() when ref_policy is not one of KEEPREF, DELREF, or ACKED. The reference policy controls how consumer-group pending entries are treated when acknowledging-and-deleting, and Redis only accepts those three literal tokens. It is a DataError.
Solutions
- Use exactly one of 'KEEPREF', 'DELREF', or 'ACKED' (uppercase) for ref_policy.
- If the value comes from user input, normalize to uppercase and validate against the allowed set before calling.
Example fix
# before
client.xackdel('mystream', 'mygroup', '1234-0', ref_policy='keepref')
# after
client.xackdel('mystream', 'mygroup', '1234-0', ref_policy='KEEPREF') Defensive patterns
Strategy: validation
Validate before calling
VALID_REF_POLICIES = {'KEEPREF', 'DELREF', 'ACKED'}
if ref_policy not in VALID_REF_POLICIES:
raise ValueError(f'ref_policy must be one of {VALID_REF_POLICIES}')
client.xackdel(name, group, *ids, ref_policy=ref_policy) Type guard
from typing import Literal
def is_valid_ref_policy(p: str) -> bool:
return p in {'KEEPREF', 'DELREF', 'ACKED'}
# usage
ref_policy: Literal['KEEPREF', 'DELREF', 'ACKED'] = 'KEEPREF' Try / catch
from redis.exceptions import DataError
try:
client.xackdel(name, group, *ids, ref_policy=ref_policy)
except DataError as e:
if 'ref_policy' in str(e):
client.xackdel(name, group, *ids, ref_policy='KEEPREF') Prevention
- Annotate ref_policy with Literal['KEEPREF','DELREF','ACKED'] so type checkers catch typos.
- Normalize config/user input to uppercase and validate against the allowed set before calling.
When it happens
Trigger: Calling client.xackdel('mystream', 'mygroup', '1234-0', ref_policy='keep') (wrong case), ref_policy='REMOVE', or any value outside the allowed set.
Common situations: Using lowercase or a typo for the policy name, or passing a user-provided string without validation.
Related errors
- XADD ref_policy must be one of: KEEPREF, DELREF, ACKED
- XACKDEL requires at least one message ID
- CLIENT KILL type must be one of
- IDMPAUTO and IDMP can only be used with id='*'
- Only one of ```idmpauto``` or ```idmp``` may be specified
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/61de02f39a8129ea.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/core.py:6932
) -> Awaitable[int]: ...
def xackdel(
self,
name: KeyT,
groupname: GroupT,
*ids: StreamIdT,
ref_policy: Literal["KEEPREF", "DELREF", "ACKED"] = "KEEPREF",
) -> int | Awaitable[int]:
"""
Combines the functionality of XACK and XDEL. Acknowledges the specified
message IDs in the given consumer group and simultaneously attempts to
delete the corresponding entries from the stream.
"""
if not ids:
raise DataError("XACKDEL requires at least one message ID")
if ref_policy not in {"KEEPREF", "DELREF", "ACKED"}:
raise DataError("XACKDEL ref_policy must be one of: KEEPREF, DELREF, ACKED")
pieces = [name, groupname, ref_policy, "IDS", len(ids)]
pieces.extend(ids)
return self.execute_command("XACKDEL", *pieces)
@overload
def xadd(
self: SyncClientProtocol,
name: KeyT,
fields: Dict[FieldT, EncodableT],
id: StreamIdT = "*",
maxlen: int | None = None,
approximate: bool = True,
nomkstream: bool = False,
minid: StreamIdT | None = None,
limit: int | None = None,
ref_policy: Literal["KEEPREF", "DELREF", "ACKED"] | None = None,
idmpauto: str | None = None,View on GitHub (pinned to 6a6b581b48)