redis/redis-py · error · DataError

start argument is not set, when end is specified

Error message

start argument is not set, when end is specified

What it means

Raised as a `DataError` by `bitpos()` (redis/commands/core.py:2790) when `start` is `None` but `end` is not. BITPOS requires a start before an end can be applied, so the client rejects an end-only range.

Solutions

  1. Provide `start` whenever you provide `end`, e.g. `r.bitpos('k', 1, start=0, end=10)`.
  2. Reorder logic so the end bound is only set when a start exists.

Example fix

// before
r.bitpos('k', 1, end=10)
// after
r.bitpos('k', 1, start=0, end=10)
Defensive patterns

Strategy: validation

Validate before calling

if end is not None and start is None:
    raise ValueError('bitpos: start is required when end is given')
r.bitpos('k', 1, start=start, end=end)

Prevention

When it happens

Trigger: `r.bitpos('k', 1, end=10)`, or any call leaving `start` at its default `None` while setting `end`.

Common situations: Keyword-only call style where the developer writes only `end=`; dynamic range building that sets `end` conditionally but always leaves `start` defaulted.

Related errors


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

Appendix: source

Thrown at redis/commands/core.py:2791

    ) -> int | Awaitable[int]:
        """
        Return the position of the first bit set to 1 or 0 in a string.
        ``start`` and ``end`` defines search range. The range is interpreted
        as a range of bytes and not a range of bits, so start=0 and end=2
        means to look at the first three bytes.

        For more information, see https://redis.io/commands/bitpos
        """
        if bit not in (0, 1):
            raise DataError("bit must be 0 or 1")
        params = [key, bit]

        start is not None and params.append(start)

        if start is not None and end is not None:
            params.append(end)
        elif start is None and end is not None:
            raise DataError("start argument is not set, when end is specified")

        if mode is not None:
            params.append(mode)
        return self.execute_command("BITPOS", *params, keys=[key])

    @overload
    def copy(
        self: SyncClientProtocol,
        source: str,
        destination: str,
        destination_db: str | None = None,
        replace: bool = False,
    ) -> bool: ...

    @overload
    def copy(
        self: AsyncClientProtocol,
        source: str,

View on GitHub (pinned to 6a6b581b48)