redis/redis-py · error · DataError
Password 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 Redis.acl_setuser() when an entry in the `passwords` list does not begin with '+' (add) or '-' (remove). Each plain-text password must be prefixed to tell Redis whether to add or remove it from the user. The library encodes each password and inspects the first byte; entries missing the prefix are rejected before the command is built.
Solutions
- Prefix every password entry with '+' to add or '-' to remove, e.g. '+secret'.
- If accepting raw input from users, prepend '+' programmatically: '+' + raw_password.
- Validate the prefix in your config/form layer before calling acl_setuser.
Example fix
# before
client.acl_setuser('alice', passwords=['secret'])
# after
client.acl_setuser('alice', passwords=['+secret']) Defensive patterns
Strategy: validation
Validate before calling
def normalize_passwords(passwords):
out = []
for p in list_or_args(passwords, []):
if not (p.startswith('+') or p.startswith('-')):
p = '+' + p # default to add
out.append(p)
return out
def safe_acl_setuser_passwords(client, username, passwords):
return client.acl_setuser(username, passwords=normalize_passwords(passwords)) Type guard
def is_prefixed_password(p) -> bool:
return isinstance(p, str) and len(p) > 1 and p[0] in '+-' Try / catch
from redis.exceptions import DataError
try:
client.acl_setuser('alice', passwords=passwords)
except DataError as e:
if 'must be prefixed' in str(e):
passwords = ['+' + p if not p[:1] in '+-' else p for p in passwords]
client.acl_setuser('alice', passwords=passwords)
else:
raise Prevention
- Always prefix password entries with '+'/'-' in config and forms.
- Wrap acl_setuser in a helper that enforces the prefix convention.
- Document the convention for operators editing ACL config files.
When it happens
Trigger: Calling client.acl_setuser('alice', passwords=['secret']) (no prefix), passwords=['secret', '+other'] (only some prefixed), or passwords=['=secret'] (wrong prefix). A single string is accepted for convenience but still needs the prefix.
Common situations: Assuming the client adds an implicit '+' for you; passing raw user-entered passwords; mixing prefixed and unprefixed entries in a list.
Related errors
- Category " " must be prefixed with "+" or
- Command " " must be prefixed with "+" or
- Hashed password must be prefixed with a "+" to add or a "-"…
- Cannot set 'nopass' and supply 'passwords' or…
- ACL LOG count must be an integer
AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10).
Data as JSON: /api/errors/2493cab3609ed1f2.
Report an issue: GitHub.
Appendix: 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 6a6b581b48)