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
bitpos() interprets an optional search range as [start, end]; end is only meaningful with a start. The guard at core.py:2790 rejects an end without a start because Redis BITPOS positional args require start before end.
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 da03cdc7e8)
Solutions
- Always provide start when you provide end, e.g. r.bitpos('key', 1, start=0, end=10).
- If you want the whole string, omit both start and end.
- When constructing from optional config, set start=0 as the default whenever end is provided.
Example fix
# before
r.bitpos('key', 1, end=10)
# after
r.bitpos('key', 1, start=0, end=10) Defensive patterns
Strategy: validation
Validate before calling
if end is not None and start is None:
start = 0
r.bitpos('key', bit, start=start, end=end) Type guard
def valid_bitpos_range(start, end) -> bool:
return not (end is not None and start is None) Try / catch
from redis.exceptions import DataError
try:
r.bitpos('key', bit, start=start, end=end)
except DataError as e:
if 'start argument is not set' in str(e):
r.bitpos('key', bit, start=0, end=end)
else:
raise Prevention
- Provide start whenever you provide end; think of the range as a mandatory pair.
- Default start=0 in your own wrapper if callers may omit it.
When it happens
Trigger: r.bitpos('key', 1, end=10) with start left at its default None. The elif at core.py:2790 catches start is None and end is not None.
Common situations: Calling bitpos with keyword-only end expecting it to mean 'first 10 bytes'; refactoring that dropped the start argument; building params from a dict that only set end.
Related errors
- Both start and end must be specified
- bit must be 0 or 1
- Only one of IFEQ/IFNE/IFDEQ/IFDNE may be specified
- ``ex``, ``px``, ``exat``, ``pxat``, and ``persist`` are mutu
- ``byfloat`` and ``byint`` are mutually exclusive.
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/0ff909dfedb09ef5.json.
Report an issue: GitHub.