redis/redis-py · error · ResponseError

Wrong number of response items from pipeline execution

Error message

Wrong number of response items from pipeline execution

What it means

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.

Solutions

  1. Use a dedicated connection for pubsub/push notifications, separate from the pipeline connection.
  2. Update to the latest redis-py (RESP3 push handling is improved across releases).
  3. Reduce the transaction to the minimum command set to isolate which command corrupts the reply count.

Example fix

// before
client = redis.asyncio.Redis(protocol=3)  # pubsub + tx on one conn
async with client.pipeline(transaction=True) as pipe:
    ...
// after
client = redis.asyncio.Redis(protocol=3)
pubsub_client = redis.asyncio.Redis(protocol=3)  # separate conn for pubsub
async with client.pipeline(transaction=True) as pipe:
    ...
Defensive patterns

Strategy: try-catch

Validate before calling

# Prevent by separating push-capable uses (pubsub, RESP3 pushes)
# from MULTI/EXEC onto different connections.
client_tx = redis.asyncio.Redis(protocol=3)
client_pubsub = redis.asyncio.Redis(protocol=3)

Try / catch

from redis.exceptions import ResponseError
try:
    await pipe.execute()
except ResponseError as e:
    if 'Wrong number of response items' in str(e):
        # connection was force-disconnected; recreate pipeline and retry once
        ...

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/13ac6c5b43fd0daf. Report an issue: GitHub.

Appendix: source

Thrown at redis/asyncio/client.py:2082

        except ExecAbortError as err:
            if errors:
                raise errors[0][1] from err
            raise

        # EXEC clears any watched keys
        self.watching = False

        if response is None:
            raise WatchError("Watched variable changed.") from None

        # put any parse errors into the response
        for i, e in errors:
            response.insert(i, e)

        if len(response) != len(commands):
            if self.connection:
                await self.connection.disconnect()
            raise ResponseError(
                "Wrong number of response items from pipeline execution"
            ) from None

        # find any errors in the response and raise if necessary
        if raise_on_error:
            self.raise_first_error(commands, response)

        # We have to run response callbacks manually
        data = []
        for r, cmd in zip(response, commands):
            if not isinstance(r, Exception):
                args, options = cmd
                command_name = args[0]

                # Remove keys entry, it needs only for cache.
                options.pop("keys", None)

                if command_name in self.response_callbacks:

View on GitHub (pinned to 6a6b581b48)