redis/redis-py · error · DataError
Invalid input of type
Error message
Invalid input of type: '{typename}'. Convert to a bytes, string, int or float first. What it means
Raised by Encoder.encode() (redis/_parsers/encoders.py:29) when the value is not one of bytes/bytearray/memoryview/bool/int/float/str. Common culprits are None, list, dict, tuple, and custom objects. The encoder only handles the primitive RESP-serializable types, so anything else raises DataError naming the offending type.
Solutions
- Serialize complex types before sending: json.dumps(obj).encode() or another codec.
- Convert None to an explicit sentinel bytes value if None is meaningful.
- For lists, spread elements across the right command (RPUSH key *items) rather than passing one list arg.
- Add a pre-send normalization layer so only primitives reach the client.
Example fix
# before
r.set("user", {"id": 1, "name": "x"}) # DataError: Invalid input of type: 'dict'
# after
import json
r.set("user", json.dumps({"id": 1, "name": "x"})) Defensive patterns
Strategy: type-guard
Validate before calling
# Reject non-primitive values before they reach the encoder
def encode_safe(v):
if not isinstance(v, (bytes, bytearray, memoryview, int, float, str)):
raise TypeError(f"serialize {type(v).__name__} before sending to Redis")
return v
r.set("k", encode_safe(json.dumps(payload))) Type guard
def is_encodable(v) -> bool:
return isinstance(v, (bytes, bytearray, memoryview, str, int, float)) and not isinstance(v, bool) Try / catch
from redis.exceptions import DataError
try:
r.set("k", value)
except DataError as e:
if "Invalid input of type" in str(e):
r.set("k", json.dumps(value)) Prevention
- Serialize dicts/lists/objects with json/pickle/str before sending.
- Convert meaningful None to an explicit sentinel bytes value.
- Spread list elements across the correct command (e.g. RPUSH key *items) rather than passing a list as one arg.
When it happens
Trigger: r.set('k', None), r.set('k', [1,2,3]), r.set('k', {'a':1}), or passing a dataclass/object instance directly. Any arg routed through the encoder that isn't a primitive triggers it.
Common situations: Forgetting to serialize complex types; passing None where a value is expected; treating Redis like a Python object store without a codec; list-as-single-arg instead of spreading elements (e.g. RPUSH needs *items).
Related errors
- Invalid input of type: 'bool'. Convert to a bytes, string…
- <dynamic TypeError message from hiredis.pack_command>
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/4bcb2aed0204a1bd.
Report an issue: GitHub.
Appendix: source
Thrown at redis/_parsers/encoders.py:29
self.encoding_errors = encoding_errors
self.decode_responses = decode_responses
def encode(self, value):
"Return a bytestring or bytes-like representation of the value"
if isinstance(value, (bytes, bytearray, memoryview)):
return value
elif isinstance(value, bool):
# special case bool since it is a subclass of int
raise DataError(
"Invalid input of type: 'bool'. Convert to a "
"bytes, string, int or float first."
)
elif isinstance(value, (int, float)):
value = repr(value).encode()
elif not isinstance(value, str):
# a value we don't know how to deal with. throw an error
typename = type(value).__name__
raise DataError(
f"Invalid input of type: '{typename}'. "
f"Convert to a bytes, string, int or float first."
)
if isinstance(value, str):
value = value.encode(self.encoding, self.encoding_errors)
return value
def decode(self, value, force=False):
"Return a unicode string from the bytes-like representation"
if self.decode_responses or force:
if isinstance(value, memoryview):
value = value.tobytes()
if isinstance(value, bytes):
value = value.decode(self.encoding, self.encoding_errors)
return value
View on GitHub (pinned to 6a6b581b48)