redis/redis-py · critical · InvalidResponse
Protocol Error: {raw!r}
Error message
Protocol Error: {raw!r} What it means
Raised by the sync RESP3 parser when the first byte of a reply line matches none of RESP3's type markers (-, !, +, _, :, (, ,, #, $, =, *, ~, %, >). Because RESP3 accepts more types than RESP2, hitting this is an even stronger signal of genuine wire corruption or a protocol-version mismatch (e.g. the server didn't actually upgrade to RESP3, or sent RESP2 framing). redis.exceptions.InvalidResponse; the raw bytes are included.
Source
Thrown at redis/_parsers/resp3.py:158
self._read_response(
disable_decoding=disable_decoding,
push_request=push_request,
timeout=timeout,
)
for _ in range(int(response))
]
response = self.handle_push_response(response)
# if this is a push request return the push response
if push_request:
return response
return self._read_response(
disable_decoding=disable_decoding,
push_request=push_request,
)
else:
raise InvalidResponse(f"Protocol Error: {raw!r}")
if isinstance(response, bytes) and disable_decoding is False:
response = self.encoder.decode(response)
return response
class _AsyncRESP3Parser(_AsyncRESPBase, AsyncPushNotificationsParser):
def __init__(self, socket_read_size):
super().__init__(socket_read_size)
self.pubsub_push_handler_func = self.handle_pubsub_push_response
self.invalidation_push_handler_func = None
async def handle_pubsub_push_response(self, response):
logger = getLogger("push_response")
logger.debug("Push response: %s", response)
return response
View on GitHub (pinned to 6a6b581b48)
Solutions
- Let the client negotiate the protocol (omit protocol=) instead of forcing protocol=3 against an old server.
- Confirm the server version supports RESP3 (Redis >= 6).
- Verify the endpoint is Redis and that TLS matches.
- Remove non-RESP proxies.
- For RESP2-only servers, set protocol=2.
Example fix
# before - forcing RESP3 against an old server r = redis.Redis(host='oldredis', protocol=3) # server is Redis 5 -> InvalidResponse: Protocol Error # after - match protocol to the server (or upgrade the server to Redis >= 6) r = redis.Redis(host='oldredis', protocol=2) # or: r = redis.Redis(host='redis6', protocol=3)
Defensive patterns
Strategy: validation
Validate before calling
# Probe the server's RESP capabilities before locking in protocol=3
import socket
def server_supports_resp3(host, port, timeout=2):
s = socket.create_connection((host, port), timeout)
try:
s.sendall(b'*2\r\n$4\r\nHELLO\r\n$1\r\n3\r\n')
first = s.recv(1)
return first in (b'%', b'-') # map reply (ok) or -NOPROTO (not supported)
finally:
s.close() Type guard
from redis.exceptions import InvalidResponse
def is_resp3_protocol_error(e: BaseException) -> bool:
return isinstance(e, InvalidResponse) and str(e).startswith('Protocol Error') Try / catch
from redis.exceptions import InvalidResponse
try:
r.get('k')
except InvalidResponse as e:
raise SystemExit(f'Not valid RESP3 - check server version/protocol/TLS: {e}') from e Prevention
- Don't force protocol=3 on Redis < 6; let the client negotiate or set protocol=2.
- InvalidResponse here usually means a HELLO/RESP3 mismatch or a non-RESP endpoint - not a transient fault; don't retry.
When it happens
Trigger: Server that ignored HELLO 3 and stays on RESP2 while the client expects RESP3 types; a Redis < 6 (no RESP3) with protocol=3 forced; a proxy that strips HELLO; a custom module returning an unsupported RESP type; wrong endpoint / non-RESP service; TLS/plaintext mismatch; buffer corruption from a prior interrupted read.
Common situations: Talking to Redis 5 (or older) with protocol=3 forced; an old RESP2-only Redis behind a new client default (RESP3 is the default on the wire now); a module returning a type the parser doesn't recognize; a corrupting proxy.
Related errors
- Protocol Error: {raw!r}
- Connection closed by server.
- Wrong number of response items from pipeline execution
- protocol must be an integer
- protocol must be either 2 or 3
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/cf50f5fc2c4f0203.
Report an issue: GitHub.