{"id":"ff7ba4cefb914d0c","repo":"redis/redis-py","slug":"migrate-requires-at-least-one-key","errorCode":null,"errorMessage":"MIGRATE requires at least one key","messagePattern":"MIGRATE requires at least one key","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":1836,"sourceCode":"\n        The ``timeout``, specified in milliseconds, indicates the maximum\n        time the connection between the two servers can be idle before the\n        command is interrupted.\n\n        If ``copy`` is True, the specified ``keys`` are NOT deleted from\n        the source server.\n\n        If ``replace`` is True, this operation will overwrite the keys\n        on the destination server if they exist.\n\n        If ``auth`` is specified, authenticate to the destination server with\n        the password provided.\n\n        For more information, see https://redis.io/commands/migrate\n        \"\"\"\n        keys = list_or_args(keys, [])\n        if not keys:\n            raise DataError(\"MIGRATE requires at least one key\")\n        pieces = []\n        if copy:\n            pieces.append(b\"COPY\")\n        if replace:\n            pieces.append(b\"REPLACE\")\n        if auth:\n            pieces.append(b\"AUTH\")\n            pieces.append(auth)\n        pieces.append(b\"KEYS\")\n        pieces.extend(keys)\n        return self.execute_command(\n            \"MIGRATE\", host, port, \"\", destination_db, timeout, *pieces, **kwargs\n        )\n\n    @overload\n    def object(self: SyncClientProtocol, infotype: str, key: KeyT, **kwargs) -> Any: ...\n\n    @overload","sourceCodeStart":1818,"sourceCodeEnd":1854,"githubUrl":"https://github.com/redis/redis-py/blob/da03cdc7e8731092b13e395605c3c1fb2de25de1/redis/commands/core.py#L1818-L1854","documentation":"Raised by migrate when the keys argument resolves to an empty list. migrate accepts keys as either a single key or a list (via list_or_args), and after flattening it checks that at least one key remains. Migrating zero keys is a protocol error on the server, so the client rejects it early.","triggerScenarios":"Calling r.migrate('host', 6379, [], 0, 5000) with an empty list. Passing keys=[] from a dynamic query that returned no results. Passing keys as a single empty string.","commonSituations":"Batch-migrating keys selected by a SCAN query that matched nothing. Conditional migration where the key set is empty at runtime. Passing an empty list as a placeholder.","solutions":["Ensure the keys collection is non-empty before calling migrate.","Guard dynamic key lists: if not keys: skip or log instead of migrating.","If migrating a single key, pass it directly or as a one-element list."],"exampleFix":"# before\nr.migrate('host', 6379, selected_keys, 0, 5000)  # selected_keys is []\n# after\nif selected_keys:\n    r.migrate('host', 6379, selected_keys, 0, 5000)","handlingStrategy":"validation","validationCode":"from redis.helpers import list_or_args\nkeys = list_or_args(keys, [])\nif not keys:\n    raise ValueError('migrate requires at least one key')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always check that the key set is non-empty before migrate.","When migrating SCAN results, short-circuit on empty batches."],"tags":["key-management","migration","validation","dataerror"],"analyzedSha":"da03cdc7e8731092b13e395605c3c1fb2de25de1","analyzedAt":"2026-08-04T20:26:47.563Z","schemaVersion":2}