redis/redis-py · error · ValueError

collect fields must be '*' or a non-empty list of names

Error message

collect fields must be '*' or a non-empty list of names

What it means

Raised by the collect reducer constructor when the fields argument is a list/iterable that is empty or contains blank (whitespace-only) names. COLLECT projects fields from each grouped row, so at least one real field name (or the '*' wildcard) is mandatory. The literal '*' is handled separately and bypasses this check.

Source

Thrown at redis/commands/search/reducers.py:236

        - **distinct**: When ``True``, emit ``DISTINCT`` to deduplicate entries
            with identical projected fields. Forward-compatible: this option is
            not yet implemented by the server and currently produces a server
            error when sent.
        - **sort_by**: An ``Asc``/``Desc`` instance or an iterable of them, used
            to order the collected entries within each group.
        - **limit**: An ``(offset, count)`` pair. Returns at most ``count``
            entries per group after skipping ``offset``. With ``sort_by`` this
            acts as a top-N selection.
        """
        args: list[str] = []

        # FIELDS (required)
        if fields == "*":
            args += ["FIELDS", "*"]
        else:
            names = [fields] if isinstance(fields, str) else list(fields)
            if not names or any(not n.strip() for n in names):
                raise ValueError(
                    "collect fields must be '*' or a non-empty list of names"
                )
            names = [_ensure_at_prefix(n) for n in names]
            args += ["FIELDS", str(len(names))] + names

        # DISTINCT (optional)
        if distinct:
            args += ["DISTINCT"]

        # SORTBY (optional)
        if sort_by is not None:
            sort_fields = [sort_by] if isinstance(sort_by, (Asc, Desc)) else sort_by
            sort_args: list[str] = []
            for f in sort_fields:
                sort_args += [_ensure_at_prefix(f.field), f.DIRSTRING]
            if not sort_args:
                raise ValueError("collect sort_by must contain at least one field")
            args += ["SORTBY", str(len(sort_args))] + sort_args

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass '*' to project every field: collect(fields='*').
  2. Supply a non-empty list of real names: collect(fields=['price', 'name']).
  3. Validate before constructing: collect(fields=names) only when names and all(n.strip() for n in names).

Example fix

// before
collect(fields=selected or [])
// after
collect(fields=selected if selected else '*')
Defensive patterns

Strategy: validation

Validate before calling

def coerce_collect_fields(fields):
    if fields in (None, '', []):
        return '*'
    if isinstance(fields, str):
        return fields
    names = [n for n in fields if n and n.strip()]
    return names if names else '*'

# usage: collect(fields=coerce_collect_fields(raw))

Type guard

def valid_collect_fields(fields) -> bool:
    if fields == '*':
        return True
    names = [fields] if isinstance(fields, str) else list(fields or [])
    return bool(names) and all(n.strip() for n in names)

Try / catch

try:
    collect(fields=raw_fields)
except ValueError:
    collect(fields='*')

Prevention

When it happens

Trigger: collect(fields=[]) or collect(fields=['']) or collect(fields=['a', ' ']). Also collect(fields=names) where names resolved to an empty list at runtime.

Common situations: Dynamically generating the field list from user selection or schema introspection that returned nothing; stripping names and producing blanks; passing an empty generator.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/bd11357e53e16767.json. Report an issue: GitHub.