redis/redis-py · error · ValueError
Bad query type {type(query)}
Error message
Bad query type {type(query)} What it means
Raised by _mk_query_args() (used by search(), explain(), etc.) when the query argument is neither a str nor a Query object. Strings are auto-wrapped in Query(); any other type is rejected. The library refuses to guess how to serialize arbitrary objects into a RediSearch query string.
Source
Thrown at redis/commands/search/commands.py:1309
args = []
if len(query_params) > 0:
args.append("PARAMS")
args.append(len(query_params) * 2)
for key, value in query_params.items():
args.append(key)
args.append(value)
return args
def _mk_query_args(
self, query, query_params: Optional[Dict[str, Union[str, int, float, bytes]]]
):
args = [self.index_name]
if isinstance(query, str):
# convert the query from a text to a query object
query = Query(query)
if not isinstance(query, Query):
raise ValueError(f"Bad query type {type(query)}")
args += query.get_args()
args += self.get_params_args(query_params)
return args, query
def search(
self,
query: Union[str, Query],
query_params: Union[Dict[str, Union[str, int, float, bytes]], None] = None,
):
"""
Search the index for a given query, and return a result of documents
### Parameters
- **query**: the search query. Either a text for simple queries with
default parameters, or a Query object for complex queries.View on GitHub (pinned to da03cdc7e8)
Solutions
- Pass a query string (e.g. '@title:hello') or a Query object.
- Build a Query: from redis.commands.search import Query; Query('@title:hello').
- For aggregation-style requests, use client.aggregate(AggregateRequest(...)) instead.
Example fix
// before
client.search({'title': 'hello'})
// after
client.search('@title:hello')
// or
client.search(Query('@title:hello').paging(0, 10)) Defensive patterns
Strategy: type-guard
Validate before calling
from redis.commands.search import Query
def safe_search(client, query, query_params=None):
if isinstance(query, str):
query = Query(query)
elif not isinstance(query, Query):
raise TypeError(f"query must be str or Query, got {type(query)}")
return client.search(query, query_params=query_params) Type guard
from redis.commands.search import Query
def is_search_query(v) -> bool:
return isinstance(v, (str, Query)) Try / catch
try:
client.search(query)
except ValueError as e:
if "Bad query type" in str(e):
client.search(Query(str(query)))
else:
raise Prevention
- Always pass either a query string or a Query object — never a dict.
- Centralize query construction in one helper that returns a Query.
- For aggregation needs, use aggregate(AggregateRequest(...)).
When it happens
Trigger: Call client.search(query) where query is an int, dict, list, None, or an arbitrary object that is not a Query instance and not a string.
Common situations: Passing a parsed JSON object or dict as the query; passing None by mistake; passing an AggregateRequest (wrong API — that goes to aggregate()).
Related errors
- Cannot use FIELDNAME alias with no field
- Bad query
- Must provide AggregateRequest object or Query object.
- Non-Sortable non-Indexable fields are ignored
- Cannot set 'sortable' or 'no_index' in Vector fields.
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/128b6c4212cc708d.json.
Report an issue: GitHub.