redis/redis-py · error · InvalidPipelineStack

Unexpected response length for cluster pipeline EXEC. Comman

Error message

Unexpected response length for cluster pipeline EXEC. Command stack was {} but response had length {}

What it means

Raised as InvalidPipelineStack after EXEC when len(response) != len(self._command_queue). The EXEC reply must contain exactly one entry per queued command; a length mismatch means the protocol stream is desynchronized (a command produced an empty/extra reply, or a response was miscounted). This is an internal-consistency assertion that usually indicates a library or server-side protocol bug rather than user data.

Source

Thrown at redis/asyncio/cluster.py:3430

        except ExecAbortError:
            if errors:
                raise errors[0]
            raise

        self._executing = False

        # EXEC clears any watched keys
        self._watching = False

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

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

        if len(response) != len(self._command_queue):
            raise InvalidPipelineStack(
                "Unexpected response length for cluster pipeline EXEC."
                " Command stack was {} but response had length {}".format(
                    [c.args[0] for c in self._command_queue], len(response)
                )
            )

        # find any errors in the response and raise if necessary
        if raise_on_error or len(errors) > 0:
            await self._raise_first_error(
                response,
                self._command_queue,
                start_time,
            )

        # We have to run response callbacks manually
        data = []
        for r, cmd in zip(response, self._command_queue):
            if not isinstance(r, Exception):

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Upgrade redis-py to the latest patch release — protocol-length mismatches are usually fixed promptly.
  2. Isolate which queued command triggers the mismatch by reducing the pipeline to a minimal reproducer and report it with the redis-py and Redis server versions.
  3. As a workaround, run the suspect command outside the pipeline (await client.execute_command(...)) until the bug is fixed.
Defensive patterns

Strategy: try-catch

Try / catch

from redis.exceptions import InvalidPipelineStack
try:
    await pipe.execute()
except InvalidPipelineStack as e:
    logger.error('protocol desync: %s', e)
    # reduce pipeline to minimal repro; upgrade redis-py; file issue

Prevention

When it happens

Trigger: Executing a cluster pipeline transaction where some queued command has EMPTY_RESPONSE kwargs that interact unexpectedly, or where a response callback / parser dropped or added an entry; also observable after server-side aborts that return a partial EXEC.

Common situations: Using commands whose response shaping is non-standard inside a cluster pipeline; version mismatch between client and server (new command returning unexpected framing); rare parser bugs.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/54c241aacffd65da.json. Report an issue: GitHub.