redis/redis-py · error · RedisClusterException

Cannot identify slot number for command: {args[0]},it cannot

Error message

Cannot identify slot number for command: {args[0]},it cannot be triggered in a transaction

What it means

Raised in _execute_command when the pipeline is in WATCH/immediate mode, the command is NOT in NO_SLOTS_COMMANDS, but _determine_slot() returned None. The library treats the command as key-bearing but could not compute a slot for it, so it cannot route it inside a transaction.

Source

Thrown at redis/asyncio/cluster.py:3158

        slot_number: Optional[int] = None
        if args[0] not in self.NO_SLOTS_COMMANDS:
            slot_number = await self._pipe.cluster_client._determine_slot(*args)

        if (
            self._watching or args[0] in self.IMMEDIATE_EXECUTE_COMMANDS
        ) and not self._explicit_transaction:
            if args[0] == "WATCH":
                self._validate_watch()

            if slot_number is not None:
                if self._pipeline_slots and slot_number not in self._pipeline_slots:
                    raise CrossSlotTransactionError(
                        "Cannot watch or send commands on different slots"
                    )

                self._pipeline_slots.add(slot_number)
            elif args[0] not in self.NO_SLOTS_COMMANDS:
                raise RedisClusterException(
                    f"Cannot identify slot number for command: {args[0]},"
                    "it cannot be triggered in a transaction"
                )

            return self._immediate_execute_command(*args, **kwargs)
        else:
            if slot_number is not None:
                self._pipeline_slots.add(slot_number)

            return super().execute_command(*args, **kwargs)

    def _validate_watch(self):
        if self._explicit_transaction:
            raise RedisError("Cannot issue a WATCH after a MULTI")

        self._watching = True

    async def _immediate_execute_command(self, *args, **options):

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Run the offending command outside the transactional pipeline (await client.execute_command(...)) so the normal cluster routing path handles it.
  2. If it is a known command missing from NO_SLOTS_COMMANDS or the key spec, open an issue / add the command's key spec to the library so _determine_slot can resolve it.
  3. Use a hash-tagged key as the first argument if the command accepts one, so a slot can be derived.

Example fix

// before
await pipe.watch('k')
await pipe.execute_command('FT.SEARCH', 'idx', 'q')  # no slot -> raises [82]
// after
res = await client.ft('idx').search('q')  # outside the transaction
Defensive patterns

Strategy: validation

Validate before calling

# Confirm the command can resolve a slot before issuing it in a watched pipeline
slot = await client._determine_slot(*args)
if slot is None and args[0] not in pipe.NO_SLOTS_COMMANDS:
    raise ValueError(f'{args[0]} cannot be routed in a transaction')

Try / catch

from redis.exceptions import RedisClusterException
try:
    await pipe.execute_command(*args)
except RedisClusterException as e:
    if 'Cannot identify slot number' in str(e):
        await client.execute_command(*args)  # outside the txn

Prevention

When it happens

Trigger: Issuing a command that is absent from the NO_SLOTS_COMMANDS allowlist yet has no key the slot resolver can use (e.g. a custom/module command, or a command form whose key position the library doesn't know) while inside a WATCH or pre-MULTI immediate-execution path of a cluster pipeline.

Common situations: Using a module command (RediSearch, RedisJSON, etc.) or a newly added Redis command inside a cluster transaction before the library's COMMAND metadata knows its key specification; calling such a command after WATCH().

Related errors


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