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() (redis/commands/search/commands.py:1514) as a ValueError when the query argument is neither an AggregateRequest nor a Query. FT.PROFILE can profile either a SEARCH or an AGGREGATE, so the client requires one of those two typed objects to know which sub-command to issue.

Solutions

  1. Wrap strings: index.profile(Query('*')).
  2. For aggregation profiling pass the AggregateRequest itself: index.profile(AggregateRequest('*')).
  3. Do not pass a Cursor or result object - pass the request.

Example fix

# before
index.profile('*', limited=True)
# after
from redis.commands.search.query import Query
index.profile(Query('*'), limited=True)
Defensive patterns

Strategy: type-guard

Validate before calling

from redis.commands.search.query import Query
from redis.commands.search.aggregation import AggregateRequest

def safe_profile(index, query, limited=False):
    if not isinstance(query, (Query, AggregateRequest)):
        raise TypeError('profile() requires a Query or AggregateRequest')
    return index.profile(query, limited=limited)

Type guard

from redis.commands.search.query import Query
from redis.commands.search.aggregation import AggregateRequest

def is_profile_query(q) -> bool:
    return isinstance(q, (Query, AggregateRequest))

Try / catch

try:
    index.profile(query, limited=True)
except ValueError as e:
    if 'AggregateRequest object or Query' in str(e):
        index.profile(Query(str(query)), limited=True)
    else:
        raise

Prevention

When it happens

Trigger: Calling index.profile('*' ), index.profile(None), index.profile({...}), or passing a Cursor (Cursor is valid for aggregate() but not for profile()).

Common situations: Passing a raw query string instead of wrapping it in Query(...), or passing an AggregateResult/Cursor where the request object is expected.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/afb746a510072034. Report an issue: GitHub.

Appendix: 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 6a6b581b48)