redis/redis-py · error · DataError
<dynamic TypeError message from hiredis.pack_command>
Error message
<dynamic TypeError message from hiredis.pack_command>
What it means
Raised by HiredisRespSerializer.pack when hiredis.pack_command raises a TypeError on a command argument that cannot be encoded to bytes. The library catches the TypeError and re-raises it as a redis.exceptions.DataError, preserving the original TypeError message (so the exact text is dynamic). Typical causes: passing None, a dict, a list, or another non-encodable object as a command argument when the hiredis protocol serializer is active.
Source
Thrown at redis/connection.py:142
class HiredisRespSerializer:
def pack(self, *args: List):
"""Pack a series of arguments into the Redis protocol"""
output = []
if isinstance(args[0], str):
args = tuple(args[0].encode().split()) + args[1:]
elif b" " in args[0]:
args = tuple(args[0].split()) + args[1:]
args = tuple(
bytes(arg) if isinstance(arg, (bytearray, memoryview)) else arg
for arg in args
)
try:
output.append(hiredis.pack_command(args))
except TypeError:
_, value, traceback = sys.exc_info()
raise DataError(value).with_traceback(traceback)
return output
class PythonRespSerializer:
def __init__(self, buffer_cutoff, encode) -> None:
self._buffer_cutoff = buffer_cutoff
self.encode = encode
def pack(self, *args):
"""Pack a series of arguments into the Redis protocol"""
output = []
# the client might have included 1 or more literal arguments in
# the command name, e.g., 'CONFIG GET'. The Redis server expects these
# arguments to be sent separately, so split the first argument
# manually. These arguments should be bytestrings so that they are
# not encoded.
if isinstance(args[0], str):View on GitHub (pinned to 6a6b581b48)
Solutions
- Inspect the exact TypeError text in the raised DataError to find which argument failed to encode.
- Convert the offending argument to str/bytes/int before sending (e.g., str(value), or skip None-valued fields).
- Strip None values from command payloads (common with HSET/MSET over partial records).
- If you must debug, reproduce with the pure-Python parser (protocol without hiredis) to see encoding details, then fix the value.
Example fix
// before
client.hset('user:1', mapping={'name':'alice','email':None})
// after
mapping = {'name':'alice'}
if email is not None:
mapping['email'] = email
client.hset('user:1', mapping=mapping) Defensive patterns
Strategy: validation
Validate before calling
def encode_safe(value):
if value is None:
raise ValueError('None cannot be sent as a command argument')
return value
# strip None values before sending
mapping = {k: v for k, v in record.items() if v is not None}
client.hset('user:1', mapping=mapping) Type guard
def is_encodable(value) -> bool:
return isinstance(value, (str, bytes, bytearray, int, float)) Try / catch
from redis.exceptions import DataError
try:
client.execute_command(*args)
except DataError as e:
# inspect e.args[0] for the underlying TypeError message
args = [a if a is not None else '' for a in args]
client.execute_command(*args) Prevention
- Strip None from mappings/lists before sending commands.
- Coerce non-primitive types (dict/list) to JSON or appropriate encodings explicitly.
- Watch for this specifically when hiredis is installed; test with realistic values.
When it happens
Trigger: Any client.execute_command / convenience call where an argument is None, a dict, a nested list, or another Python object that is neither str/bytes/bytearray/int. Happens only when the hiredis parser/serializer is installed (hiredis >= 3.2.0); the pure-Python serializer has different encoding behavior and may not raise identically.
Common situations: Passing None where a value is required (e.g., hset with a None field value). Sending a dict or nested structure the library does not auto-serialize. A field that is sometimes None due to upstream data. Version change enabling hiredis where previously the pure-Python path tolerated the value.
Related errors
- Connection closed by server.
- Maintenance notifications are only supported with hiredis an
- Connection closed by server.
- Buffer is closed.
- Invalid input of type: 'bool'. Convert to a bytes, string, i
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/502935adbb272b09.
Report an issue: GitHub.