redis/redis-py · error · ValueError

Subcommand not found in command

Error message

Subcommand {subcommand_name} not found in command {command_name}

What it means

Raised by the sync CommandsParser._is_keyless_command() (redis/_parsers/commands.py:245) when a subcommand name is not present among the parent command's 'subcommands' list (from COMMAND output). It is raised as ValueError and is consumed internally by get_command_policies() to classify subcommands as keyless/keyed for cluster routing.

Solutions

  1. Inspect the command's 'subcommands' entries (COMMAND INFO <cmd>) to see the exact subcommand identifier strings the server reports.
  2. Align the Redis server version across cluster nodes so subcommand names are consistent.
  3. Upgrade redis-py to a release that understands the subcommand naming your server uses.
  4. If reached via a custom code path, pass the subcommand name in the server's expected 'parent|child' form.
Defensive patterns

Strategy: validation

Validate before calling

# Confirm a subcommand exists in the parent's subcommands list before classifying
info = r.execute_command("COMMAND", "INFO", "PUBSUB")[0]
sub_names = {s[0] for s in (info[9] if len(info) > 9 else [])}
if f"PUBSUB|{sub}".upper() not in {n.decode().upper() if isinstance(n, bytes) else n.upper() for n in sub_names}:
    raise ValueError("subcommand not registered on server")

Prevention

When it happens

Trigger: get_command_policies() iterates subcommands and calls _is_keyless_command(command, subcommand_name); if the subcommand_name doesn't string-match any subcommand[0] entry (expected 'PUBSUB|NUMSUB' form), this ValueError fires. Happens with formatting mismatches or server-version variance in subcommand naming.

Common situations: Server version exposing different/renamed subcommands than the client expects; module subcommands with non-standard naming; partial or reordered COMMAND output; internal invariant break after concurrent reinitialization.

Related errors


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

Appendix: source

Thrown at redis/_parsers/commands.py:245

                The name of the subcommand to check, if applicable. If not provided,
                the check is performed only on the command.

        Returns:
            bool
                True if the specified command or subcommand is considered keyless,
                False otherwise.

        Raises:
            ValueError
                If the specified subcommand is not found within the command or the
                specified command does not exist in the available commands.
        """
        if subcommand_name:
            for subcommand in self.commands.get(command_name)["subcommands"]:
                if str_if_bytes(subcommand[0]) == subcommand_name:
                    parsed_subcmd = self.parse_subcommand(subcommand)
                    return parsed_subcmd["first_key_pos"] <= 0
            raise ValueError(
                f"Subcommand {subcommand_name} not found in command {command_name}"
            )
        else:
            command_details = self.commands.get(command_name, None)
            if command_details is not None:
                return command_details["first_key_pos"] <= 0

            raise ValueError(f"Command {command_name} not found in commands")

    def get_command_policies(self) -> PolicyRecords:
        """
        Retrieve and process the command policies for all commands and subcommands.

        This method traverses through commands and subcommands, extracting policy details
        from associated data structures and constructing a dictionary of commands with their
        associated policies. It supports nested data structures and handles both main commands
        and their subcommands.

View on GitHub (pinned to 6a6b581b48)