{"record":{"id":"518c0b8fc66acd8d","repo":"redis/redis-py","slug":"xadd-idmp-must-be-a-tuple-of-producer-id-idempot","errorCode":null,"errorMessage":"XADD idmp must be a tuple of (producer_id, idempotent_id)","messagePattern":"XADD idmp must be a tuple of \\(producer_id, idempotent_id\\)","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":7035,"sourceCode":"\n        if idmpauto is not None and idmp is not None:\n            raise DataError(\"Only one of ```idmpauto``` or ```idmp``` may be specified\")\n\n        if (idmpauto is not None or idmp is not None) and id != \"*\":\n            raise DataError(\"IDMPAUTO and IDMP can only be used with id='*'\")\n\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)","sourceCodeStart":7017,"sourceCodeEnd":7053,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L7017-L7053","documentation":"Raised by xadd() when the idmp argument is not a 2-element tuple. idmp must be exactly (producer_id, idempotent_id) so the client can emit 'IDMP <producer_id> <idempotent_id>' on the wire; lists, shorter/longer tuples, or wrong types are rejected. It is a DataError.","triggerScenarios":"Calling client.xadd('s', fields, idmp=['p1', b'iid']) (list not tuple), idmp=('p1',) (length 1), or idmp='p1' (string).","commonSituations":"Using a list instead of a tuple, omitting the idempotent_id, or passing a pre-flattened value.","solutions":["Pass idmp as a tuple of exactly two elements: (producer_id, idempotent_id), e.g. ('producer-1', b'msg-uuid').","Ensure the second element is the bytes idempotent_id unique per message."],"exampleFix":"# before\nclient.xadd('s', {'f': 'v'}, idmp=['p1', b'iid'])\n\n# after\nclient.xadd('s', {'f': 'v'}, idmp=('p1', b'iid'))","handlingStrategy":"type-guard","validationCode":"if not isinstance(idmp, tuple) or len(idmp) != 2:\n    raise ValueError('idmp must be a 2-tuple (producer_id, idempotent_id)')\nclient.xadd(name, fields, idmp=idmp)","typeGuard":"from typing import Any\n\ndef is_valid_idmp(v: Any) -> bool:\n    return isinstance(v, tuple) and len(v) == 2\n\n# usage\nif not is_valid_idmp(idmp):\n    raise TypeError('idmp must be (producer_id, idempotent_id)')","tryCatchPattern":"from redis.exceptions import DataError\ntry:\n    client.xadd(name, fields, idmp=idmp)\nexcept DataError as e:\n    if 'idmp must be a tuple' in str(e):\n        client.xadd(name, fields, idmp=tuple(idmp))","preventionTips":["Construct idmp as a literal tuple: ('producer-1', b'msg-uuid').","If sourcing from a list, convert with tuple() and assert length 2 before calling."],"tags":["streams","xadd","idempotency","type-check","validation"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}