redis/redis-py · error · DataError

genpass optionally accepts a bits argument, between 0 and…

Error message

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

What it means

Raised by Redis.acl_genpass() when the optional `bits` argument cannot be converted to an integer, or is outside the inclusive range 0..4096. The library catches a ValueError from int() conversion or the explicit range check and re-raises it as a DataError with a descriptive message. This is the same constraint the server enforces for ACL GENPASS.

Solutions

  1. Ensure `bits` is an int in [0, 4096] before calling; coerce with int(bits) and clamp/validate upstream.
  2. Omit `bits` entirely to use the server default.
  3. Validate with a small helper that raises your own configuration error with context.

Example fix

# before
client.acl_genpass(bits=8192)
# after
bits = int(config_bits)
if not 0 <= bits <= 4096:
    raise ValueError(f'bits out of range: {bits}')
client.acl_genpass(bits=bits)
Defensive patterns

Strategy: validation

Validate before calling

def safe_acl_genpass(client, bits=None):
    if bits is not None:
        b = int(bits)
        if not 0 <= b <= 4096:
            raise ValueError(f'bits must be in [0, 4096], got {b}')
    return client.acl_genpass(bits=b if bits is None else int(bits))

Type guard

def is_valid_genpass_bits(bits) -> bool:
    try:
        return 0 <= int(bits) <= 4096
    except (TypeError, ValueError):
        return False

Try / catch

from redis.exceptions import DataError
try:
    token = client.acl_genpass(bits=bits)
except DataError as e:
    if 'bits argument' in str(e):
        token = client.acl_genpass()  # fall back to server default
    else:
        raise

Prevention

When it happens

Trigger: Calling client.acl_genpass(bits) where bits is a non-numeric string (e.g. 'random'), None passed via keyword incorrectly, a negative int, an int greater than 4096, or a float like 100.5 (int() truncates but 4097/−1 still fail the range check).

Common situations: Generating ACL passwords programmatically with a user-supplied bit length; passing a config value that was loaded as a string and not coerced to int; assuming default is 256 but supplying 0 expecting 'unlimited'.

Related errors


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

Appendix: 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 6a6b581b48)