The 'NOPERM this user has no permissions' error occurs in Redis 6+ when an authenticated user attempts to execute a command, access a key, or publish to a channel they don't have permission for. This happens due to Access Control Lists (ACL) restricting the user's capabilities. Fixing this requires granting appropriate permissions through ACL configuration.
The "NOPERM this user has no permissions" error indicates that your Redis user account has been configured with Access Control Lists (ACL) that restrict what they can do. This is a security feature introduced in Redis 6.0 that replaced the simpler AUTH-only model. Redis ACLs can restrict: - **Commands**: Which Redis commands a user can execute (SET, GET, DEL, PUBLISH, SUBSCRIBE, etc.) - **Keys**: Which key patterns a user can access (e.g., only keys matching "session:*") - **Channels**: Which pub/sub channels a user can publish to or subscribe from - **Database**: Which Redis database(s) a user can access The error is particularly common when: - Upgrading from Redis 5 to Redis 6+ with ACL enabled - Using managed Redis services (AWS ElastiCache, Azure Cache, Google Cloud Memorystore) with pre-configured ACL policies - Connecting with an application user that has intentionally restricted permissions - Using pub/sub features with channel restrictions
First, understand exactly what command or key access is failing:
# The error message typically tells you what's missing:
# "NOPERM this user has no permissions to run the 'SET' 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"Check the exact error from your application or using redis-cli:
# Connect with your user
redis-cli -u redis://username:password@localhost:6379
# Try the failing command
> SET mykey "value"
(error) NOPERM this user has no permissions to run the 'SET' command or its subcommand
# Or for key access issues
> GET user:123:session
(error) NOPERM this user has no permissions to access one of the keys used as argumentsDocument what command/key/channel is failing - you'll need this for granting permissions.
Use the ACL SETUSER command to add missing command permissions:
# Connect as admin (default user or admin ACL user)
redis-cli -u redis://default:adminpass@localhost:6379
# Grant a specific command permission
ACL SETUSER myuser +SET
# Grant multiple commands
ACL SETUSER myuser +SET +GET +DEL
# Grant all commands in a category
ACL SETUSER myuser +@string # All string commands
ACL SETUSER myuser +@list # All list commands
ACL SETUSER myuser +@hash # All hash commands
ACL SETUSER myuser +@set # All set commands
ACL SETUSER myuser +@sortedset
# Grant all commands
ACL SETUSER myuser +@all
# View current user permissions
ACL GETUSER myuserCommon command categories:
- @string: SET, GET, APPEND, STRLEN, INCR, etc.
- @list: LPUSH, RPUSH, LPOP, RPOP, LRANGE, etc.
- @hash: HSET, HGET, HMSET, HDEL, etc.
- @set: SADD, SREM, SMEMBERS, SUNION, etc.
- @sorted_set / @zset: ZADD, ZRANGE, ZREM, etc.
- @pubsub: PUBLISH, SUBSCRIBE, PSUBSCRIBE, etc.
- @admin: CONFIG, SHUTDOWN, SAVE, BGSAVE, etc.
- @all: All commands (most permissive)
If the error mentions key access, configure which keys the user can access:
# Connect as admin
redis-cli -u redis://default:adminpass@localhost:6379
# Allow access to all keys
ACL SETUSER myuser ~*
# Allow access to specific key patterns
ACL SETUSER myuser ~session:* # Only keys starting with "session:"
ACL SETUSER myuser ~user:123:* # Only keys starting with "user:123:"
# Allow multiple patterns
ACL SETUSER myuser ~session:* ~cache:* ~temp:*
# Verify permissions
ACL GETUSER myuserKey pattern tips:
- ~* = all keys (most permissive)
- ~prefix:* = keys starting with prefix
- Patterns use glob-style matching
- Users can have multiple key patterns
- If no key patterns specified, user has no key access
If using pub/sub and getting channel permission errors (common in Redis 7.0+):
# Connect as admin
redis-cli -u redis://default:adminpass@localhost:6379
# Allow all channels
ACL SETUSER myuser &*
# Allow specific channel patterns
ACL SETUSER myuser ¬ifications:*
ACL SETUSER myuser &alerts:* &events:*
# View current channel permissions
ACL GETUSER myuserFor Redis 7.0+ compatibility:
By default, Redis 7.0 uses acl-pubsub-default=resetchannels, which restricts channels. To restore Redis 6 behavior:
# In redis.conf or via CONFIG SET
acl-pubsub-default allchannels
# Or set via command (requires CONFIG permission)
CONFIG SET acl-pubsub-default allchannelsAfter changing:
# Users need explicit channel permissions
ACL SETUSER myuser &* # Grant all channelsSome client libraries require certain commands during connection (e.g., INFO, HELLO, PING):
# Connect as admin
redis-cli -u redis://default:adminpass@localhost:6379
# Grant common library requirements
ACL SETUSER myuser +PING
ACL SETUSER myuser +HELLO
ACL SETUSER myuser +INFO
ACL SETUSER myuser +COMMAND
# For ioredis library, also grant:
ACL SETUSER myuser +SELECT # For database selectionLibrary-specific fixes:
ioredis:
// Option 1: Disable ready check (avoids INFO requirement)
const redis = new Redis({
host: 'localhost',
port: 6379,
username: 'myuser',
password: 'password',
enableReadyCheck: false, // Disables the INFO check
});
// Option 2: Grant INFO permission
// ACL SETUSER myuser +INFOredis-py (Python):
# Ensure user has these permissions
# ACL SETUSER myuser +PING +COMMAND
import redis
r = redis.Redis(host='localhost', username='myuser', password='password')node-redis:
// Grant these commands to the ACL user
// +PING, +COMMAND, +HELLO
import { createClient } from 'redis';
const client = createClient({
username: 'myuser',
password: 'password',
});For Redis Sentinel or Cluster setups, ACL must be configured on each node:
Redis Sentinel:
# Connect to sentinel (default port 26379)
redis-cli -p 26379
# Grant permissions for sentinel monitoring
ACL SETUSER myuser +PING +INFO +COMMAND
# Sentinel-specific commands
ACL SETUSER myuser +SENTINELRedis Cluster:
# Connect to any cluster node
redis-cli -c -u redis://username:password@localhost:6379
# Grant cluster commands
ACL SETUSER myuser +CLUSTER +ASKING +READONLY
# Standard permissions
ACL SETUSER myuser +@all ~*Managed Services (ElastiCache, Azure Cache, Google Cloud):
# For AWS ElastiCache, use the console or CLI:
aws elasticache modify-user \
--user-id myuser \
--access-string "on ~* &* +@all" # Grant all permissions
# For Azure Cache for Redis (managed ACL):
# Use Azure Portal or az cli to update user permissions
# For Google Cloud Memorystore:
# Use gcloud memorystore redis users update commandAfter modifying ACL permissions, save the configuration and test:
# Save ACL configuration to disk
redis-cli ACL SAVE
# Or in redis-cli:
> ACL SAVE
OK
# List all users and their permissions
redis-cli ACL LIST
# Get specific user details
redis-cli ACL GETUSER myuser
# Test the connection with the user
redis-cli -u redis://myuser:password@localhost:6379
# Try the previously failing command
> SET testkey "value"
OK
# Verify it works
> GET testkey
"value"Restart Redis (if needed):
# If changes were made to redis.conf, restart Redis
sudo systemctl restart redis-server
# Or for Docker:
docker restart myredis-containerFor Sentinel/Cluster:
# Ensure each node has the same ACL configuration
# Check all nodes have the updated user:
for node in node1 node2 node3; do
redis-cli -h $node ACL GETUSER myuser
doneUnderstanding Redis ACL
Redis ACLs provide fine-grained access control with three components:
1. User: An authenticated identity with a username and password
2. Permissions: What the user can do (commands, keys, channels)
3. State: Whether the user is enabled/disabled
The default user is "default" and has full permissions (+@all).
ACL Permission Syntax
+command Add a command
-command Remove a command
+@category Add a category of commands
-@category Remove a category
~pattern Add key pattern
~* Add all keys (must use with + commands)
&pattern Add channel pattern
+@all All commands (includes all categories)Migration from Redis 5 to Redis 6+
When upgrading:
1. Old AUTH-only connections become the "default" user
2. New ACL-based users must be explicitly created and granted permissions
3. The "default" user initially keeps full permissions for backward compatibility
4. To enforce ACL strictly, change requirepass to use username+password
# Old Redis 5 style (still works as default user in Redis 6+)
requirepass mypassword
# New Redis 6+ style (uses ACL)
# requirepass removed, instead:
ACL SETUSER default on >mypassword ~* &* +@allManaged Service Considerations
AWS ElastiCache, Azure Cache, Google Cloud Memorystore, and Redis Cloud have their own ACL management:
- Some don't allow direct ACL SETUSER commands
- Must use service-specific tools (CLI, console, Terraform)
- Default users may have specific naming conventions
- Backup and restore operations may reset ACL configurations
Performance Impact
ACL checks add minimal overhead (<1% in typical workloads), but:
- Very restrictive key patterns can slow down wildcard key operations
- High-volume pub/sub with channel restrictions may need tuning
- For extreme performance requirements, consider using Redis Cluster with per-slot ACLs
Security Best Practices
1. Don't use the "default" user for applications; create dedicated users
2. Use principle of least privilege: grant only needed permissions
3. Rotate passwords regularly
4. Audit ACL changes with monitoring/logging
5. Never grant +@admin to application users
6. For pub/sub, explicitly allow only needed channels
7. Use key patterns to isolate data between applications
ERR Unbalanced XREAD list of streams
How to fix "ERR Unbalanced XREAD list" in Redis
ERR syntax error
How to fix "ERR syntax error" in Redis
ConnectionError: Error while reading from socket
ConnectionError: Error while reading from socket in redis-py
ERR unknown command
How to fix ERR unknown command in Redis
Command timed out
How to fix 'Command timed out' in ioredis