redis/redis-py · error · DataError
Invalid input of type: '{typename}'. Convert to a bytes, str
Error message
Invalid input of type: '{typename}'. Convert to a bytes, string, int or float first. What it means
Raised by Encoder.encode() for any value that is not bytes/bytearray/memoryview, bool, int, float, or str. The typename in the message is type(value).__name__, so the message tells you exactly what was passed (e.g. 'NoneType', 'list', 'dict', 'Decimal', 'datetime'). DataError is a RedisError subclass.
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 da03cdc7e8)
Solutions
- Serialize structured objects to bytes/str: json.dumps(value).encode().
- Flatten collections: r.lpush('k', *items) instead of r.lpush('k', items).
- Coerce numerics: int()/float() for Decimal/numpy scalars before passing.
- Handle None explicitly: skip the call, or store a sentinel like b''.
Example fix
// before
r.set("doc", {"a": 1}) # DataError: dict
r.lpush("list", [1, 2, 3]) # DataError: list
// after
import json
r.set("doc", json.dumps({"a": 1}))
r.lpush("list", *[1, 2, 3]) Defensive patterns
Strategy: validation
Validate before calling
# Whitelist scalar types before sending
def coerce_for_redis(v):
if isinstance(v, bool) or not isinstance(v, (bytes, bytearray, memoryview, int, float, str)):
raise TypeError(f"unsupported type {type(v).__name__}; serialize first")
return v Type guard
def is_redis_scalar(v) -> bool:
return isinstance(v, (bytes, bytearray, memoryview, int, float, str)) and not isinstance(v, bool) Try / catch
try:
r.set("k", value)
except redis.exceptions.DataError as e:
if "Invalid input of type" in str(e):
import json
r.set("k", json.dumps(value)) # serialize structured data Prevention
- Serialize structured objects (dict/list/dataclass) with json/pickle/msgpack before Redis.
- Flatten collections with *unpacking for variadic commands (LPUSH, SADD).
- Coerce Decimal/numpy to int/float explicitly.
- Handle None with an explicit sentinel or skip the call.
When it happens
Trigger: Passing None, list, dict, tuple, Decimal, datetime, UUID, dataclass, Pydantic model, numpy scalar, pandas NA, or any custom object as a command value or argument. Common: r.set('k', None), r.lpush('list', [1,2,3]) instead of *list, r.hset('h', mapping={'a': Decimal('1.2')}).
Common situations: Forgetting to serialize structured data (use json.dumps / pickle / msgpack); passing None instead of an empty bytestring; third-party numeric types (Decimal, numpy) that are not int/float; nested collections passed where a flat value is expected.
Related errors
- Invalid input of type: 'bool'. Convert to a bytes, string, i
- CLIENT KILL skipme must be a bool
- client_id must be a list
- CLIENT PAUSE timeout must be an integer
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/4bcb2aed0204a1bd.json.
Report an issue: GitHub.