redis/redis-py · error · DataError
Password {i} must be prefixed with a "+" to add or a "-" to
Error message
Password {i} must be prefixed with a "+" to add or a "-" to remove What it means
Raised by acl_setuser() as a DataError when an entry in the passwords iterable does not start with '+' (add) or '-' (remove). Each password must carry an explicit add/remove prefix because ACL SETUSER encodes them as >pwd / <pwd respectively. The 0-based index i of the offending entry is included. See redis/commands/core.py:490-500.
Source
Thrown at redis/commands/core.py:497
pieces.append(b"off")
if (passwords or hashed_passwords) and nopass:
raise DataError(
"Cannot set 'nopass' and supply 'passwords' or 'hashed_passwords'"
)
if passwords:
# as most users will have only one password, allow remove_passwords
# to be specified as a simple string or a list
passwords = list_or_args(passwords, [])
for i, password in enumerate(passwords):
password = encoder.encode(password)
if password.startswith(b"+"):
pieces.append(b">%s" % password[1:])
elif password.startswith(b"-"):
pieces.append(b"<%s" % password[1:])
else:
raise DataError(
f"Password {i} must be prefixed with a "
f'"+" to add or a "-" to remove'
)
if hashed_passwords:
# as most users will have only one password, allow remove_passwords
# to be specified as a simple string or a list
hashed_passwords = list_or_args(hashed_passwords, [])
for i, hashed_password in enumerate(hashed_passwords):
hashed_password = encoder.encode(hashed_password)
if hashed_password.startswith(b"+"):
pieces.append(b"#%s" % hashed_password[1:])
elif hashed_password.startswith(b"-"):
pieces.append(b"!%s" % hashed_password[1:])
else:
raise DataError(
f"Hashed password {i} must be prefixed with a "
f'"+" to add or a "-" to remove'View on GitHub (pinned to da03cdc7e8)
Solutions
- Prefix each password with '+' to add or '-' to remove, e.g. ['+secret'].
- If you only ever add, normalize: passwords = ['+' + p for p in raw_passwords].
- Validate prefixes in your config loader so the error never reaches the client.
Example fix
# before
r.acl_setuser('alice', enabled=True, passwords=['hunter2', '2ndpwd'])
# after
r.acl_setuser('alice', enabled=True, passwords=['+hunter2', '+2ndpwd']) Defensive patterns
Strategy: validation
Validate before calling
def _prefixed(items):
for i, p in enumerate(items):
if p[:1] not in ('+', '-'):
raise ValueError(f'password {i} needs +/- prefix')
return items
client.acl_setuser(username, passwords=_prefixed(passwords or [])) Type guard
def passwords_are_prefixed(passwords) -> bool:
return all(p[:1] in ('+', '-') for p in (passwords or [])) Try / catch
from redis.exceptions import DataError
try:
client.acl_setuser(username, passwords=passwords)
except DataError:
passwords = ['+' + p for p in passwords] # assume add
client.acl_setuser(username, passwords=passwords) Prevention
- Normalize bare passwords to '+' prefixed at the config layer.
- Store the +/- sign alongside each password in your ACL model.
When it happens
Trigger: Calling r.acl_setuser(username, passwords=['secret']) (no prefix), or passwords=['+good', 'bad'] where the second entry lacks a prefix. A single prefixed string is also accepted via list_or_args.
Common situations: Storing passwords without prefixes and passing them straight through; UI/config that collects bare passwords; assuming the client adds '+' implicitly like some other tools.
Related errors
- Cannot set 'nopass' and supply 'passwords' or 'hashed_passwo
- Hashed password {i} must be prefixed with a "+" to add or a
- Category "{category}" must be prefixed with "+" or "-"
- Command "{cmd}" must be prefixed with "+" or "-"
- genpass optionally accepts a bits argument, between 0 and 40
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/2493cab3609ed1f2.json.
Report an issue: GitHub.