redis/redis-py · error · DataError
Hashed password must be prefixed with a "+" to add or a "-"…
Error message
Hashed 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 `hashed_passwords` list does not begin with '+' (add) or '-' (remove). Like plain passwords, each SHA-256 hashed password must be prefixed to indicate add vs remove. The library inspects the first byte of the encoded entry and rejects missing prefixes.
Solutions
- Prefix every hashed_passwords entry with '+' to add or '-' to remove.
- Generate the hash correctly: hashlib.sha256(password.encode()).hexdigest(), then prepend '+' or '-'.
- If migrating from plain passwords, switch to the `passwords` argument instead and let Redis hash them server-side.
Example fix
# before
import hashlib
h = hashlib.sha256(b'secret').hexdigest()
client.acl_setuser('alice', hashed_passwords=[h])
# after
client.acl_setuser('alice', hashed_passwords=['+' + h]) Defensive patterns
Strategy: validation
Validate before calling
import hashlib
def make_hashed_password(cleartext: str, remove: bool = False) -> str:
h = hashlib.sha256(cleartext.encode()).hexdigest()
return ('-' if remove else '+') + h
def normalize_hashed(items):
out = []
for h in list_or_args(items, []):
if not (h.startswith('+') or h.startswith('-')):
h = '+' + h
out.append(h)
return out Type guard
def is_prefixed_hashed(h) -> bool:
return isinstance(h, str) and len(h) > 1 and h[0] in '+-' Try / catch
from redis.exceptions import DataError
try:
client.acl_setuser('alice', hashed_passwords=hashed)
except DataError as e:
if 'must be prefixed' in str(e):
hashed = ['+' + h if not h[:1] in '+-' else h for h in hashed]
client.acl_setuser('alice', hashed_passwords=hashed)
else:
raise Prevention
- Always prefix hashed password entries with '+'/'-'.
- Prefer the `passwords` argument to let Redis hash server-side when possible.
- Generate hashes with a helper that prepends the prefix automatically.
When it happens
Trigger: Calling client.acl_setuser('alice', hashed_passwords=['5e88...']) with no prefix, or with a wrong prefix. Hashed passwords are SHA-256 hex strings of the cleartext password and must still carry '+'/'-' on the client side.
Common situations: Precomputing SHA-256 hashes and forgetting the prefix; porting hashes from redis-cli ACL SETUSER syntax that uses '#'/'!' separators (those are added internally by the client based on '+'/'-').
Related errors
- Category " " must be prefixed with "+" or
- Command " " must be prefixed with "+" or
- Password must be prefixed with a "+" to add or a "-" to…
- 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/91300caf0de6c1cf.
Report an issue: GitHub.
Appendix: source
Thrown at redis/commands/core.py:513
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'
)
if nopass:
pieces.append(b"nopass")
if categories:
for category in categories:
category = encoder.encode(category)
# categories can be prefixed with one of (+@, +, -@, -)
if category.startswith(b"+@"):
pieces.append(category)
elif category.startswith(b"+"):
pieces.append(b"+@%s" % category[1:])
elif category.startswith(b"-@"):
pieces.append(category)
elif category.startswith(b"-"):View on GitHub (pinned to 6a6b581b48)