{"record":{"id":"13ac6c5b43fd0daf","repo":"redis/redis-py","slug":"wrong-number-of-response-items-from-pipeline-execu","errorCode":null,"errorMessage":"Wrong number of response items from pipeline execution","messagePattern":"Wrong number of response items from pipeline execution","errorType":"exception","errorClass":"ResponseError","httpStatus":null,"severity":"error","filePath":"redis/asyncio/client.py","lineNumber":2082,"sourceCode":"        except ExecAbortError as err:\n            if errors:\n                raise errors[0][1] from err\n            raise\n\n        # EXEC clears any watched keys\n        self.watching = False\n\n        if response is None:\n            raise WatchError(\"Watched variable changed.\") from None\n\n        # put any parse errors into the response\n        for i, e in errors:\n            response.insert(i, e)\n\n        if len(response) != len(commands):\n            if self.connection:\n                await self.connection.disconnect()\n            raise ResponseError(\n                \"Wrong number of response items from pipeline execution\"\n            ) from None\n\n        # find any errors in the response and raise if necessary\n        if raise_on_error:\n            self.raise_first_error(commands, response)\n\n        # We have to run response callbacks manually\n        data = []\n        for r, cmd in zip(response, commands):\n            if not isinstance(r, Exception):\n                args, options = cmd\n                command_name = args[0]\n\n                # Remove keys entry, it needs only for cache.\n                options.pop(\"keys\", None)\n\n                if command_name in self.response_callbacks:","sourceCodeStart":2064,"sourceCodeEnd":2100,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/asyncio/client.py#L2064-L2100","documentation":"Raised in _execute_transaction after EXEC: the number of items in the EXEC response does not equal the number of queued commands. This indicates a protocol-level desynchronization — the client and server disagree on how many replies are outstanding — so the connection is forcibly disconnected and a ResponseError is raised.","triggerScenarios":"A bug or race that drops a queued command from the stack mid-flight, a RESP3 push message being consumed as a command reply, or a server-side issue returning a short/long array. Disconnecting is intentional to reset the socket.","commonSituations":"Using modules/commands that emit out-of-band pushes interleaved with a MULTI/EXEC on the same connection; mixing pubsub and transactions on one connection; corrupted state after a partial network failure.","solutions":["Use a dedicated connection for pubsub/push notifications, separate from the pipeline connection.","Update to the latest redis-py (RESP3 push handling is improved across releases).","Reduce the transaction to the minimum command set to isolate which command corrupts the reply count."],"exampleFix":"// before\nclient = redis.asyncio.Redis(protocol=3)  # pubsub + tx on one conn\nasync with client.pipeline(transaction=True) as pipe:\n    ...\n// after\nclient = redis.asyncio.Redis(protocol=3)\npubsub_client = redis.asyncio.Redis(protocol=3)  # separate conn for pubsub\nasync with client.pipeline(transaction=True) as pipe:\n    ...","handlingStrategy":"try-catch","validationCode":"# Prevent by separating push-capable uses (pubsub, RESP3 pushes)\n# from MULTI/EXEC onto different connections.\nclient_tx = redis.asyncio.Redis(protocol=3)\nclient_pubsub = redis.asyncio.Redis(protocol=3)","typeGuard":null,"tryCatchPattern":"from redis.exceptions import ResponseError\ntry:\n    await pipe.execute()\nexcept ResponseError as e:\n    if 'Wrong number of response items' in str(e):\n        # connection was force-disconnected; recreate pipeline and retry once\n        ...","preventionTips":["Never share one connection between pubsub/push and a transaction.","Keep transactions short and avoid commands that emit out-of-band pushes."],"tags":["pipeline","transaction","resp3","protocol","desync"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}