redis/redis-py · error · DataError

genpass optionally accepts a bits argument, between 0 and 40

Error message

genpass optionally accepts a bits argument, between 0 and 4096.

What it means

Raised by acl_genpass() as a DataError when the bits argument is supplied but is not coercible to int, or is outside the inclusive range 0..4096. The guard at redis/commands/core.py:202-211 wraps int conversion + range check in a try/except ValueError, re-raising as DataError (a RedisError subclass). The bound matches the Redis server's ACL GENPASS limit.

Source

Thrown at redis/commands/core.py:209

    ) -> Awaitable[bytes | str]: ...

    def acl_genpass(self, bits: int | None = None, **kwargs) -> (
        bytes | str
    ) | Awaitable[bytes | str]:
        """Generate a random password value.
        If ``bits`` is supplied then use this number of bits, rounded to
        the next multiple of 4.
        See: https://redis.io/commands/acl-genpass
        """
        pieces = []
        if bits is not None:
            try:
                b = int(bits)
                if b < 0 or b > 4096:
                    raise ValueError
                pieces.append(b)
            except ValueError:
                raise DataError(
                    "genpass optionally accepts a bits argument, between 0 and 4096."
                )
        return self.execute_command("ACL GENPASS", *pieces, **kwargs)

    @overload
    def acl_getuser(
        self: SyncClientProtocol, username: str, **kwargs
    ) -> ACLGetUserData: ...

    @overload
    def acl_getuser(
        self: AsyncClientProtocol, username: str, **kwargs
    ) -> Awaitable[ACLGetUserData]: ...

    def acl_getuser(
        self, username: str, **kwargs
    ) -> ACLGetUserData | Awaitable[ACLGetUserData]:
        """

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Pass an int in [0, 4096] (or None for the default 256-bit password).
  2. Validate and clamp the input before calling: bits = max(0, min(4096, int(bits))).
  3. If accepting user input as a string, confirm it is a clean integer literal before calling acl_genpass.

Example fix

# before
r.acl_genpass(bits=user_input)  # user_input='64.0' or 5000
# after
bits = int(user_input)
if not 0 <= bits <= 4096:
    raise ValueError('bits must be 0..4096')
r.acl_genpass(bits=bits)
Defensive patterns

Strategy: validation

Validate before calling

def valid_bits(bits):
    if bits is None:
        return None
    b = int(bits)  # raises ValueError for bad input -> convert to DataError yourself
    if not 0 <= b <= 4096:
        raise ValueError('bits must be in [0, 4096]')
    return b
client.acl_genpass(bits=valid_bits(bits))

Type guard

def is_valid_bits(bits) -> bool:
    if bits is None:
        return True
    try:
        return 0 <= int(bits) <= 4096
    except (TypeError, ValueError):
        return False

Try / catch

from redis.exceptions import DataError
try:
    client.acl_genpass(bits=bits)
except DataError:
    client.acl_genpass(bits=None)  # fall back to default

Prevention

When it happens

Trigger: Calling r.acl_genpass(bits) where bits is a non-numeric string, None handled fine (omitted), a float outside range, a negative int, an int > 4096, or something whose int() raises (e.g. 'foo', '16.5', [1]). Note int('16') works, but int('16.5') raises.

Common situations: Reading bits from config/env as a string without conversion; passing a bit count larger than the documented max; copy-paste from a tutorial that uses an outdated limit; off-by-one on a UI slider bound to this value.

Related errors


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