{"id":"02b0ef858b772d4d","repo":"redis/redis-py","slug":"xadd-maxlen-must-be-non-negative-integer","errorCode":null,"errorMessage":"XADD maxlen must be non-negative integer","messagePattern":"XADD maxlen must be non-negative integer","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7041,"sourceCode":"\n        if ref_policy is not None and ref_policy not in {\"KEEPREF\", \"DELREF\", \"ACKED\"}:\n            raise DataError(\"XADD ref_policy must be one of: KEEPREF, DELREF, ACKED\")\n\n        if nomkstream:\n            pieces.append(b\"NOMKSTREAM\")\n        if ref_policy is not None:\n            pieces.append(ref_policy)\n        if idmpauto is not None:\n            pieces.extend([b\"IDMPAUTO\", idmpauto])\n        if idmp is not None:\n            if not isinstance(idmp, tuple) or len(idmp) != 2:\n                raise DataError(\n                    \"XADD idmp must be a tuple of (producer_id, idempotent_id)\"\n                )\n            pieces.extend([b\"IDMP\", idmp[0], idmp[1]])\n        if maxlen is not None:\n            if not isinstance(maxlen, int) or maxlen < 0:\n                raise DataError(\"XADD maxlen must be non-negative integer\")\n            pieces.append(b\"MAXLEN\")\n            if approximate:\n                pieces.append(b\"~\")\n            pieces.append(str(maxlen))\n        if minid is not None:\n            pieces.append(b\"MINID\")\n            if approximate:\n                pieces.append(b\"~\")\n            pieces.append(minid)\n        if limit is not None:\n            pieces.extend([b\"LIMIT\", limit])\n        pieces.append(id)\n        if not isinstance(fields, dict) or len(fields) == 0:\n            raise DataError(\"XADD fields must be a non-empty dict\")\n        for pair in fields.items():\n            pieces.extend(pair)\n        return self.execute_command(\"XADD\", name, *pieces)\n","sourceCodeStart":7023,"sourceCodeEnd":7059,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L7023-L7059","documentation":"Raised by xadd() when maxlen is provided but is not a non-negative int. MAXLEN requires a non-negative integer count; bools, floats, negatives, or string-encoded numbers are rejected because the library appends str(maxlen) directly into the command and validates type to prevent malformed commands.","triggerScenarios":"Calling client.xadd(name, fields, maxlen=-1), maxlen=10.5, maxlen='1000', or maxlen=True.","commonSituations":"Passing a config value loaded as a string; computing maxlen from a float expression; off-by-one producing a negative; passing a bool by mistake.","solutions":["Pass maxlen as a non-negative int, e.g. maxlen=1000.","Coerce/validate config values with int() and a >= 0 check before calling.","Use 0 only if you intend to trim everything (semantics may differ; prefer minid for that)."],"exampleFix":"# before\nawait r.xadd('s', {'f':'v'}, maxlen='1000')\n# after\nawait r.xadd('s', {'f':'v'}, maxlen=1000)","handlingStrategy":"type-guard","validationCode":"def validate_maxlen(maxlen):\n    if maxlen is not None and (not isinstance(maxlen, int) or isinstance(maxlen, bool) or maxlen < 0):\n        raise ValueError('maxlen must be a non-negative integer')\n    return True","typeGuard":"def is_valid_maxlen(m) -> bool:\n    return m is None or (isinstance(m, int) and not isinstance(m, bool) and m >= 0)","tryCatchPattern":null,"preventionTips":["Pass maxlen as a non-negative int (not a string or float).","Coerce config values with int() and a >= 0 guard before calling.","Remember bool is a subclass of int in Python; exclude it explicitly."],"tags":["stream","xadd","trim","validation","dataerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}