redis/redis-py · error · ValueError
Must provide AggregateRequest object or Query object.
Error message
Must provide AggregateRequest object or Query object.
What it means
Raised by profile() when the query argument is neither an AggregateRequest nor a Query. profile() dispatches to FT.PROFILE with either 'AGGREGATE' or 'SEARCH' mode, so it must know which; a Cursor, string, or any other type is rejected.
Source
Thrown at redis/commands/search/commands.py:1514
**query_params**: Define one or more value parameters.
Each parameter has a name and a value.
"""
st = time.monotonic()
cmd = [PROFILE_CMD, self.index_name, ""]
if limited:
cmd.append("LIMITED")
cmd.append("QUERY")
if isinstance(query, AggregateRequest):
cmd[2] = "AGGREGATE"
cmd += query.build_args()
elif isinstance(query, Query):
cmd[2] = "SEARCH"
cmd += query.get_args()
cmd += self.get_params_args(query_params)
else:
raise ValueError("Must provide AggregateRequest object or Query object.")
res = self.execute_command(*cmd)
return self._parse_results(
PROFILE_CMD, res, query=query, duration=(time.monotonic() - st) * 1000.0
)
def spellcheck(self, query, distance=None, include=None, exclude=None):
"""
Issue a spellcheck query
Args:
query: search query.
distance: the maximal Levenshtein distance for spelling
suggestions (default: 1, max: 4).
include: specifies an inclusion custom dictionary.
exclude: specifies an exclusion custom dictionary.View on GitHub (pinned to da03cdc7e8)
Solutions
- Pass a Query object for SEARCH profiling or an AggregateRequest for AGGREGATE profiling.
- Build the right wrapper: profile(Query('@x:1')) or profile(AggregateRequest('*')).
- If you only want the plan without timing, use explain() for searches.
Example fix
// before
client.profile('@title:hello')
// after
from redis.commands.search import Query
client.profile(Query('@title:hello')) Defensive patterns
Strategy: type-guard
Validate before calling
from redis.commands.search import Query
from redis.commands.search.aggregation import AggregateRequest
def safe_profile(client, query, limited=False, query_params=None):
if isinstance(query, str):
raise TypeError("profile() needs a Query or AggregateRequest, not a string")
if not isinstance(query, (Query, AggregateRequest)):
raise TypeError(f"query must be Query/AggregateRequest, got {type(query)}")
return client.profile(query, limited=limited, query_params=query_params) Type guard
from redis.commands.search import Query
from redis.commands.search.aggregation import AggregateRequest
def is_profile_query(v) -> bool:
return isinstance(v, (Query, AggregateRequest)) Try / catch
try:
client.profile(query)
except ValueError as e:
if "AggregateRequest object or Query object" in str(e):
from redis.commands.search import Query
client.profile(Query(str(query)))
else:
raise Prevention
- profile() picks SEARCH vs AGGREGATE from the wrapper type — pass the right one.
- Don't pass cursors to profile() — profile a fresh query instead.
- Use explain() if you only need the plan without timing.
When it happens
Trigger: Call client.profile(query) where query is a string, a Cursor, an int, None, or any type other than AggregateRequest / Query.
Common situations: Passing a raw query string (profile requires the strongly-typed object so it can pick the mode); passing a Cursor (cursors are not profiled); mixing up profile() with search()/aggregate().
Related errors
- Cannot use FIELDNAME alias with no field
- Bad query type {type(query)}
- Bad query
- 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/afb746a510072034.json.
Report an issue: GitHub.