{"record":{"id":"fdd904a9d7fe3b9a","repo":"redis/redis-py","slug":"both-start-and-end-must-be-specified","errorCode":null,"errorMessage":"Both start and end must be specified","messagePattern":"Both start and end must be specified","errorType":"validation","errorClass":"DataError","httpStatus":null,"severity":"error","filePath":"redis/commands/core.py","lineNumber":2668,"sourceCode":"    def bitcount(\n        self,\n        key: KeyT,\n        start: int | None = None,\n        end: int | None = None,\n        mode: str | None = None,\n    ) -> int | Awaitable[int]:\n        \"\"\"\n        Returns the count of set bits in the value of ``key``.  Optional\n        ``start`` and ``end`` parameters indicate which bytes to consider\n\n        For more information, see https://redis.io/commands/bitcount\n        \"\"\"\n        params = [key]\n        if start is not None and end is not None:\n            params.append(start)\n            params.append(end)\n        elif (start is not None and end is None) or (end is not None and start is None):\n            raise DataError(\"Both start and end must be specified\")\n        if mode is not None:\n            params.append(mode)\n        return self.execute_command(\"BITCOUNT\", *params, keys=[key])\n\n    def bitfield(\n        self: Union[\"redis.client.Redis\", \"redis.asyncio.client.Redis\"],\n        key: KeyT,\n        default_overflow: str | None = None,\n    ) -> BitFieldOperation:\n        \"\"\"\n        Return a BitFieldOperation instance to conveniently construct one or\n        more bitfield operations on ``key``.\n\n        For more information, see https://redis.io/commands/bitfield\n        \"\"\"\n        return BitFieldOperation(self, key, default_overflow=default_overflow)\n\n    @overload","sourceCodeStart":2650,"sourceCodeEnd":2686,"githubUrl":"https://github.com/redis/redis-py/blob/6a6b581b48225afa0b76912d1028c6035baee932/redis/commands/core.py#L2650-L2686","documentation":"Raised as a `DataError` by `bitcount()` (redis/commands/core.py:2667) when exactly one of `start`/`end` is provided. BITCOUNT's range is defined by a (start, end) pair, so the client refuses to send a partial range.","triggerScenarios":"`r.bitcount('k', start=0)`, `r.bitcount('k', end=10)`, or any call where one positional/keyword boundary is `None` and the other is an int.","commonSituations":"Passing `end` as a keyword while forgetting `start`; building ranges dynamically where one bound computes to `None` under some branch; off-by-one reasoning where the developer assumed a default for the missing bound.","solutions":["Supply both `start` and `end` together, e.g. `r.bitcount('k', start=0, end=-1)`.","Omit both to count over the whole string.","Centralize range construction so partial ranges never reach the call."],"exampleFix":"// before\nr.bitcount('k', start=0)\n// after\nr.bitcount('k', start=0, end=-1)  # whole string in byte mode","handlingStrategy":"validation","validationCode":"if (start is None) != (end is None):\n    raise ValueError('bitcount: set both start and end, or neither')\nr.bitcount('k', start=start, end=end)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat (start, end) as a single optional tuple.","Reject partial ranges at the boundary of your own API."],"tags":["bitcount","arguments","validation","dataerror"],"backgroundTag":null,"analyzedSha":"6a6b581b48225afa0b76912d1028c6035baee932","analyzedAt":"2026-08-10T12:52:44.840Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}