redis/redis-py · error · DataError

MIGRATE requires at least one key

Error message

MIGRATE requires at least one key

What it means

Raised by migrate() (redis/commands/core.py:1836) when the keys argument normalizes (via list_or_args) to an empty list. MIGRATE with no keys is invalid at the protocol level, so the library rejects it before sending. This is a redis.exceptions.DataError raised client-side.

Solutions

  1. Guard the call: if keys: r.migrate(host, port, keys, dest_db, timeout)
  2. Pass at least one key as a list: r.migrate(host, port, ["k1"], dest_db, timeout)
  3. list_or_args also accepts a single key string, so r.migrate(host, port, "k1", dest_db, timeout) works

Example fix

# before
r.migrate(host, port, selected_keys, dest_db, timeout)
# after
if selected_keys:
    r.migrate(host, port, selected_keys, dest_db, timeout)
Defensive patterns

Strategy: validation

Validate before calling

keys = list_or_args(keys, []) if not isinstance(keys, list) else keys
if not keys:
    # nothing to migrate; skip
    return
r.migrate(host, port, keys, destination_db, timeout)

Try / catch

from redis.exceptions import DataError
try:
    r.migrate(host, port, keys, dest_db, timeout)
except DataError as e:
    if "requires at least one key" in str(e):
        pass  # empty key set is a no-op
    else:
        raise

Prevention

When it happens

Trigger: Calling r.migrate(host, port, [], dest_db, timeout) with an empty list, or r.migrate(host, port, "", dest_db, timeout), or passing a variable that evaluates to no keys after list_or_args expansion.

Common situations: Migrating a dynamic key set that happens to be empty for a given shard/partition; filtering keys down to none before migrating.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:1836

        The ``timeout``, specified in milliseconds, indicates the maximum
        time the connection between the two servers can be idle before the
        command is interrupted.

        If ``copy`` is True, the specified ``keys`` are NOT deleted from
        the source server.

        If ``replace`` is True, this operation will overwrite the keys
        on the destination server if they exist.

        If ``auth`` is specified, authenticate to the destination server with
        the password provided.

        For more information, see https://redis.io/commands/migrate
        """
        keys = list_or_args(keys, [])
        if not keys:
            raise DataError("MIGRATE requires at least one key")
        pieces = []
        if copy:
            pieces.append(b"COPY")
        if replace:
            pieces.append(b"REPLACE")
        if auth:
            pieces.append(b"AUTH")
            pieces.append(auth)
        pieces.append(b"KEYS")
        pieces.extend(keys)
        return self.execute_command(
            "MIGRATE", host, port, "", destination_db, timeout, *pieces, **kwargs
        )

    @overload
    def object(self: SyncClientProtocol, infotype: str, key: KeyT, **kwargs) -> Any: ...

    @overload

View on GitHub (pinned to 6a6b581b48)