redis/redis-py · error · DataError

``ordering`` (OBO or BULK) is required when ``count`` is set

Error message

``ordering`` (OBO or BULK) is required when ``count`` is set

What it means

In lmovem(), when count is given the server requires an explicit ordering (OBO = pop-then-push stack semantics, BULK = preserve queue semantics). The guard at core.py:3675 raises DataError when count is set but ordering is None, because Redis LMOVEM rejects the command without it.

Source

Thrown at redis/commands/core.py:3676

        ``EXACTLY`` moves exactly ``count`` elements or nothing at all. When
        ``count`` is not given a single element is moved.

        ``ordering`` controls the order at the destination: ``OBO`` pushes each
        element as it is popped (reversing block order, stack semantics) while
        ``BULK`` preserves the original relative order (queue semantics). It is
        required whenever ``count`` is given.

        Returns the array of moved elements, or ``None`` if nothing was moved.

        For more information, see https://redis.io/commands/lmovem
        """
        if count is None:
            if mode is not None or ordering is not None:
                raise DataError(
                    "``count`` is required when ``mode`` or ``ordering`` is set"
                )
        elif ordering is None:
            raise DataError(
                "``ordering`` (OBO or BULK) is required when ``count`` is set"
            )
        pieces: list[EncodableT] = [first_list, second_list, src, dest]
        if count is not None:
            pieces.extend([mode or "COUNT", count, ordering])
        return self.execute_command("LMOVEM", *pieces)

    @overload
    def blmovem(
        self: SyncClientProtocol,
        first_list: str,
        second_list: str,
        timeout: float,
        src: str = "LEFT",
        dest: str = "RIGHT",
        count: int | None = None,
        mode: Literal["COUNT", "EXACTLY"] | None = None,
        ordering: Literal["OBO", "BULK"] | None = None,

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass ordering='OBO' or ordering='BULK' whenever count is set.
  2. Pick OBO to reverse block order (stack) or BULK to preserve relative order (queue) based on your list semantics.
  3. Encapsulate the (count, ordering) pair in a helper so they are never supplied independently.

Example fix

# before
r.lmovem('src', 'dst', count=3)

# after
r.lmovem('src', 'dst', count=3, ordering='BULK')
Defensive patterns

Strategy: validation

Validate before calling

if count is not None and ordering is None:
    raise ValueError("lmovem: ordering ('OBO' or 'BULK') is required when count is set")
r.lmovem('src', 'dst', count=count, ordering=ordering)

Type guard

def valid_lmovem_ordering(count, ordering) -> bool:
    return count is None or ordering in ('OBO', 'BULK')

Try / catch

from redis.exceptions import DataError
try:
    r.lmovem('src', 'dst', count=3)
except DataError as e:
    if 'ordering' in str(e):
        r.lmovem('src', 'dst', count=3, ordering='BULK')
    else:
        raise

Prevention

When it happens

Trigger: r.lmovem('src','dst', count=3) with no ordering. The check fires before the command is sent.

Common situations: Assuming a default ordering; forgetting that the multi-element variant mandates an explicit choice; copy-pasting from LMOVE (single element) which has no ordering arg.

Related errors


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