redis/redis-py · error · DataError
XADD maxlen must be non-negative integer
Error message
XADD maxlen must be non-negative integer
What it means
Raised by xadd() when maxlen is not an int or is negative. MAXLEN trimming requires a non-negative integer count; negative counts and string values like '1000' are rejected client-side before building the command. It is a DataError.
Solutions
- Pass maxlen as a non-negative int (e.g. maxlen=1000).
- Coerce config values with int() and clamp to >= 0 before calling xadd.
Example fix
# before
client.xadd('s', {'f': 'v'}, maxlen='1000')
# after
client.xadd('s', {'f': 'v'}, maxlen=1000) Defensive patterns
Strategy: type-guard
Validate before calling
if maxlen is not None and (not isinstance(maxlen, int) or isinstance(maxlen, bool) or maxlen < 0):
raise ValueError('maxlen must be a non-negative int')
client.xadd(name, fields, maxlen=maxlen) Type guard
def is_valid_maxlen(v) -> bool:
return isinstance(v, int) and not isinstance(v, bool) and v >= 0
# usage
if maxlen is not None and not is_valid_maxlen(maxlen):
raise TypeError('maxlen must be a non-negative integer') Try / catch
from redis.exceptions import DataError
try:
client.xadd(name, fields, maxlen=maxlen)
except DataError as e:
if 'maxlen must be non-negative' in str(e):
client.xadd(name, fields, maxlen=int(maxlen)) Prevention
- Coerce config-sourced maxlen with int() and clamp to >= 0.
- Watch for bool values: isinstance(True, int) is True, so guard against accidental booleans.
When it happens
Trigger: Calling client.xadd('s', fields, maxlen=-5), maxlen='1000' (string), or maxlen=1.5 (float).
Common situations: Reading maxlen from a config file as a string, computing it from an expression that can go negative, or using a float from division.
Related errors
- Only one of ```maxlen``` or ```minid``` may be specified
- XADD fields must be a non-empty dict
- XADD idmp must be a tuple of (producer_id, idempotent_id)
- 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/02b0ef858b772d4d.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/core.py:7041
if ref_policy is not None and ref_policy not in {"KEEPREF", "DELREF", "ACKED"}:
raise DataError("XADD ref_policy must be one of: KEEPREF, DELREF, ACKED")
if nomkstream:
pieces.append(b"NOMKSTREAM")
if ref_policy is not None:
pieces.append(ref_policy)
if idmpauto is not None:
pieces.extend([b"IDMPAUTO", idmpauto])
if idmp is not None:
if not isinstance(idmp, tuple) or len(idmp) != 2:
raise DataError(
"XADD idmp must be a tuple of (producer_id, idempotent_id)"
)
pieces.extend([b"IDMP", idmp[0], idmp[1]])
if maxlen is not None:
if not isinstance(maxlen, int) or maxlen < 0:
raise DataError("XADD maxlen must be non-negative integer")
pieces.append(b"MAXLEN")
if approximate:
pieces.append(b"~")
pieces.append(str(maxlen))
if minid is not None:
pieces.append(b"MINID")
if approximate:
pieces.append(b"~")
pieces.append(minid)
if limit is not None:
pieces.extend([b"LIMIT", limit])
pieces.append(id)
if not isinstance(fields, dict) or len(fields) == 0:
raise DataError("XADD fields must be a non-empty dict")
for pair in fields.items():
pieces.extend(pair)
return self.execute_command("XADD", name, *pieces)
View on GitHub (pinned to 6a6b581b48)