Redis Error Guide: 'NOPERM this user has no permissions' — Fix ACL Rules
Fix Redis 'NOPERM' errors: read the ACL rule that denied the command, key, or channel, then grant the right +command, key pattern, or pub/sub permission safely.
- #redis
- #database
- #troubleshooting
- #errors
Stuck on this Redis error? Get the free incident triage checklist
A one-page PDF — the exact steps to isolate, fix, and verify a production error like this one. No spam, unsubscribe anytime.
Overview
An authenticated Redis client is rejected the moment it runs a command, key, or channel its ACL user is not allowed to touch. Unlike an auth failure, the connection is fine — the permission is not. The error takes three shapes:
NOPERM this user has no permissions to run the 'flushall' command
NOPERM this user has no permissions to access one of the keys used as arguments
NOPERM this user has no permissions to access one of the channels used as arguments
The first is a command that is not in the user’s command allow-list; the second is a key that falls outside the user’s key patterns; the third is a SUBSCRIBE/PUBLISH channel outside the user’s channel patterns.
Symptoms
- The client authenticates successfully (
AUTHorHELLOwith username works) but specific commands fail. - Only some commands fail — reads work, writes don’t, or the reverse.
- A worker fails only on certain key prefixes while others succeed.
- Pub/Sub consumers connect but
SUBSCRIBEreturnsNOPERM. - The error appeared right after a Redis 6+ upgrade, an ACL tightening, or moving from the
defaultuser to a scoped user.
Common Root Causes
- Command not granted — the user’s rule lacks
+<command>(or a+@category) for the command being run. New code called a command outside the allow-list. - Key pattern too narrow — the rule allows
~app:*but the code touchedsession:123. Any argument key outside the pattern is denied. - Channel pattern missing — Redis 7 separated pub/sub permissions; a user needs explicit
&<pattern>(orallchannels) to useSUBSCRIBE/PUBLISH. - Category vs command mismatch — a broad
+@readwas granted but the command is classified@writeor@dangerous(e.g.FLUSHALL,KEYS). - First-arg vs multi-key commands — commands like
MSET,MGET,COPY, or Lua scripts touch multiple keys; every key must match a pattern, not just the first. - Selectors not applied — a Redis 7 selector (conditional permission block) does not cover the command/key combination the client used.
Diagnostic Workflow
Start by identifying exactly who the connection is and what it is allowed to do. Run these as an admin user with +acl permission:
# Who am I on this connection?
redis-cli -u redis://appuser:****@127.0.0.1:6379 ACL WHOAMI
# Full rule for the user — read commands, keys (~), channels (&), selectors
redis-cli ACL GETUSER appuser
# List all users at a glance
redis-cli ACL LIST
ACL GETUSER is the key command. Read its output carefully:
1) "flags" -> on / allkeys / allchannels ...
2) "passwords" -> hashes (never plaintext)
3) "commands" -> e.g. "-@all +@read +get +set"
4) "keys" -> e.g. "~app:*" (empty = no keys allowed)
5) "channels" -> e.g. "¬ify:*" (empty = no channels)
6) "selectors" -> conditional permission blocks
Confirm the failing command’s category so you know which grant is missing:
# What category does the command belong to?
redis-cli COMMAND DOCS flushall | grep -i acl
redis-cli ACL CAT # list all categories
redis-cli ACL CAT dangerous # commands in the dangerous category
Reproduce the denial deliberately and watch which of the three NOPERM variants fires — command, key, or channel — that tells you exactly which grant to add:
redis-cli -u redis://appuser:****@127.0.0.1:6379 GET session:123
# NOPERM ... access one of the keys -> key pattern problem, not command
Check the live ACL log, which records recent denials with the reason and offending object:
redis-cli ACL LOG 10
# fields: reason (command/key/channel), object (what was denied),
# username, client-info, count, age
Example Root Cause Analysis
A worker deployed fine in staging but threw NOPERM ... access one of the keys in production. ACL WHOAMI confirmed it connected as worker. ACL GETUSER worker showed:
commands: -@all +@read +@write
keys: ~jobs:*
channels: (empty)
The command allow-list was fine — +@read +@write covered LPUSH/BRPOP. But the code had started writing progress to metrics:worker:42, a key outside ~jobs:*. Every command whose argument key didn’t start with jobs: was denied.
ACL LOG 5 confirmed it:
reason: key object: metrics:worker:42 username: worker count: 214
The fix was to widen the key patterns to exactly the two prefixes the worker legitimately uses — not to allkeys:
redis-cli ACL SETUSER worker ~jobs:* ~metrics:worker:*
redis-cli ACL LIST | grep worker # verify the new rule
The worker recovered immediately. Staging had passed only because its seed data happened to keep everything under jobs:*.
Prevention Best Practices
- Grant least privilege, then test the real workload — run an integration test that exercises every command and key prefix the service uses before shipping the ACL.
- Prefer categories with explicit denies — start from
-@all, add+@read/+@write, and explicitly-@dangeroussoFLUSHALL/KEYS/DEBUGcan never slip in. - Enumerate all key prefixes a service touches and encode them as
~prefix:*patterns; remember multi-key commands need every key to match. - Grant pub/sub channels explicitly with
&pattern(Redis 7+); don’t assume key permissions cover channels. - Persist ACLs in an
aclfile(orCONFIG REWRITE) so rules survive restarts, and keep them in version control. - Watch
ACL LOGand alert on non-zero denial counts — it surfaces both misconfigurations and probing. - Never fix a NOPERM with
allkeys/allcommandsas a shortcut; that silently removes the isolation the ACL existed to provide.
Quick Command Reference
redis-cli ACL WHOAMI # current username on this connection
redis-cli ACL GETUSER appuser # full command/key/channel rule
redis-cli ACL LIST # all users, one line each
redis-cli ACL LOG 10 # recent denials with reason + object
redis-cli ACL CAT # list command categories
redis-cli ACL CAT dangerous # commands in a category
# Grant a specific command
redis-cli ACL SETUSER appuser +get +set
# Add key patterns (all listed patterns are kept)
redis-cli ACL SETUSER worker ~jobs:* ~metrics:worker:*
# Add a pub/sub channel pattern (Redis 7+)
redis-cli ACL SETUSER notifier ¬ify:*
# Persist so it survives restart
redis-cli ACL SAVE # writes to aclfile
redis-cli CONFIG REWRITE # or persist inline users to redis.conf
Conclusion
NOPERM is a permission problem, not an authentication problem — the user is who they say they are but is reaching for a command, key, or channel outside their ACL. The three variants of the message tell you immediately which grant is missing, and ACL GETUSER plus ACL LOG show you the exact rule and the offending object. Fix it by widening the specific command, key pattern, or channel the workload legitimately needs — never by falling back to allkeys/allcommands, which throws away the isolation the ACL was there to enforce.
Fixed it? Get 500 Redis & DevOps AI prompts — free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.
Did this fix your issue?
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.