redis/redis-py · error · DataError

The only valid subcommands are

Error message

The only valid subcommands are 

What it means

Raised by JSON.debug() when subcommand is not in ['MEMORY', 'HELP']. JSON.DEBUG only has two subcommands. Note the message is malformed: DataError is constructed with two positional args ("The only valid subcommands are ", str(valid_subcommands)), so str(exc) includes both as a tuple representation rather than a clean sentence.

Source

Thrown at redis/commands/json/commands.py:826

        subcommand: str,
        key: str | None = None,
        path: str | None = Path.root_path(),
    ) -> Awaitable[int | list[str]]: ...

    def debug(
        self,
        subcommand: str,
        key: str | None = None,
        path: str | None = Path.root_path(),
    ) -> (int | list[str]) | Awaitable[int | list[str]]:
        """Return the memory usage in bytes of a value under ``path`` from
        key ``name``.

        For more information see `JSON.DEBUG <https://redis.io/commands/json.debug>`_.
        """  # noqa
        valid_subcommands = ["MEMORY", "HELP"]
        if subcommand not in valid_subcommands:
            raise DataError("The only valid subcommands are ", str(valid_subcommands))
        pieces = [subcommand]
        if subcommand == "MEMORY":
            if key is None:
                raise DataError("No key specified")
            pieces.append(key)
            pieces.append(str(path))
        return self.execute_command("JSON.DEBUG", *pieces)

    @overload
    def jsonget(self: SyncClientProtocol, *args, **kwargs) -> JsonType | None: ...

    @overload
    def jsonget(
        self: AsyncClientProtocol, *args, **kwargs
    ) -> Awaitable[JsonType | None]: ...

    @deprecated_function(
        version="4.0.0", reason="redisjson-py supported this, call get directly."

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Use subcommand='MEMORY' (requires a key) or subcommand='HELP'.
  2. Uppercase the input: subcommand = subcommand.upper().
  3. If you need memory usage, call debug('MEMORY', key).

Example fix

// before
client.json().debug('memory', 'mykey')
// after
client.json().debug('MEMORY', 'mykey')
Defensive patterns

Strategy: validation

Validate before calling

VALID = {"MEMORY", "HELP"}

def json_debug(client, subcommand, key=None, path=None):
    subcommand = subcommand.upper()
    if subcommand not in VALID:
        raise ValueError(f"subcommand must be one of {VALID}, got {subcommand!r}")
    return client.json().debug(subcommand, key, path) if subcommand == "MEMORY" \
        else client.json().debug(subcommand)

Type guard

def is_valid_debug_subcommand(v) -> bool:
    return isinstance(v, str) and v.upper() in {"MEMORY", "HELP"}

Try / catch

from redis.exceptions import DataError
try:
    client.json().debug(subcommand, key)
except DataError as e:
    if "valid subcommands" in str(e):
        client.json().debug(subcommand.upper(), key)
    else:
        raise

Prevention

When it happens

Trigger: Call client.json().debug(subcommand) with subcommand not equal to 'MEMORY' or 'HELP' (case-sensitive), e.g. debug('SEGMENTS') or debug('memory') (lowercase).

Common situations: Guessing a subcommand name; case mismatch ('memory' vs 'MEMORY'); porting code from another client with different subcommand names.

Related errors


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