redis/redis-py · error · DataError
Invalid input of type: 'bool'. Convert to a bytes, string, i
Error message
Invalid input of type: 'bool'. Convert to a bytes, string, int or float first.
What it means
Raised by Encoder.encode() when the value is a bool. bool is intentionally rejected even though it is a subclass of int, because silently encoding True as b'1' (via repr(True)='True' or int True='1') is a frequent source of subtle bugs; the library forces the caller to be explicit. DataError is a RedisError subclass (error_type=SERVER).
Source
Thrown at redis/_parsers/encoders.py:20
class Encoder:
"Encode strings to bytes-like and decode bytes-like to strings"
__slots__ = "encoding", "encoding_errors", "decode_responses"
def __init__(self, encoding, encoding_errors, decode_responses):
self.encoding = encoding
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"View on GitHub (pinned to da03cdc7e8)
Solutions
- Convert the bool to int first: r.set('flag', int(True)).
- Serialize to a string the application understands: r.set('flag', 'true' if value else 'false').
- Use bytes explicitly: r.set('flag', b'1' if value else b'0').
- Sanitize values at the boundary: a helper that maps bool->int/str before any Redis call.
Example fix
// before
r.set("feature_x", user.has_feature) # DataError if has_feature is bool
// after
r.set("feature_x", int(user.has_feature)) Defensive patterns
Strategy: type-guard
Validate before calling
# Reject bool at the boundary before any Redis call
def to_redis_value(v):
if isinstance(v, bool):
raise TypeError("bool not supported; convert with int(value)")
return v
r.set("k", to_redis_value(flag)) 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("flag", value)
except redis.exceptions.DataError as e:
if "Invalid input of type: 'bool'" in str(e):
r.set("flag", int(value)) Prevention
- Convert booleans explicitly with int() at the call site.
- Add a serialization layer (Pydantic, dataclass-to-primitive) that never emits bool to Redis.
- Unit-test command helpers with bool inputs to catch this before deploy.
- Remember bool is a subclass of int - guard explicitly, isinstance(x, int) alone is not enough.
When it happens
Trigger: Passing a Python bool as a value or argument to any command: r.set('flag', True), r.setex('k', 60, False), r.hset('h', 'field', True), pipeline.set('k', some_bool). The encoder is hit when the command is encoded for the wire.
Common situations: Storing feature flags or boolean state directly; passing the result of a comparison (a == b) as a value; deserializing JSON booleans and forwarding them to Redis without conversion.
Related errors
- Invalid input of type: '{typename}'. Convert to a bytes, str
- 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/b160a9b03fba202a.json.
Report an issue: GitHub.