Fix Redis "NOAUTH Authentication Required" and WRONGPASS in Django

Fix Redis NOAUTH Authentication required and WRONGPASS invalid username-password pair errors in Django and Celery: put the password in the Redis URL correctly, URL-encode special characters, use ACL usernames, and keep cache and broker settings in sync.

Problem statement

After enabling a Redis password, moving to a managed Redis, or rotating credentials, Django or Celery fails with one of these:

redis.exceptions.AuthenticationError: Authentication required.
NOAUTH Authentication required.
WRONGPASS invalid username-password pair or user is disabled.

NOAUTH means the client sent commands without authenticating at all; the password never reached Redis. WRONGPASS means it authenticated with the wrong username or password. Both usually come from how the Redis URL is written, or from one component (cache, Celery broker, Celery results, Channels) still using the old URL.

Where auth goes wrongRedis requirespassword or ACLURL in settingsuser:pass@hostParsing or envdrops the secretAuth errorNOAUTH or WRONGPASSEvery Redis client in the project needs the credentials, each through its own setting.
  1. Put credentials in the URL: redis://:PASSWORD@host:6379/0 (note the colon before the password) or redis://USER:PASSWORD@host:6379/0 for ACL users.
  2. URL-encode special characters in the password (@ → %40, / → %2F, # → %23).
  3. Use rediss:// when the provider requires TLS.
  4. Update every client: CACHES, CELERY_BROKER_URL, CELERY_RESULT_BACKEND, CHANNEL_LAYERS, and any django-rq queues.
  5. Test with redis-cli -u "$REDIS_URL" PING from the app server.

Step-by-step solution

1. Test the URL directly

redis-cli -u "$REDIS_URL" PING

PONG means the URL works. NOAUTH or WRONGPASS here means the URL itself is wrong, independent of Django.

2. Write the URL correctly

The password goes in the user-info part of the URL. Without an ACL username, keep the leading colon:

# password only (default user)
redis://:s3cret@redis.internal:6379/0
# ACL username and password (Redis 6+)
redis://app:s3cret@redis.internal:6379/0
# TLS
rediss://app:s3cret@redis.example.com:6380/0

redis://s3cret@host without the colon is parsed as a username with no password, and Redis replies NOAUTH.

where each credential goesrediss://app:p%40ss%2Fword@redis.example.com:6380/11231Double s means TLS; required by many providers.2Provider host and TLS port; database number at the end.3Password with @ and / percent-encoded.A missing colon or an unencoded character silently drops the passworddjango-deployment.com
Test the exact URL with redis-cli -u before putting it into settings.

3. Encode special characters

Generated passwords often include characters that break URL parsing. Encode the password once:

python3 -c "import urllib.parse, getpass; print(urllib.parse.quote(getpass.getpass(), safe=''))"

Alternatively, pass the password separately. django-redis accepts "OPTIONS": {"PASSWORD": os.environ["REDIS_PASSWORD"]}, and Celery accepts broker_transport_options only for some transports, so the URL form is the most portable.

4. Update every component

A project can have four or five separate Redis clients:

REDIS_URL = os.environ["REDIS_URL"]
CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache", "LOCATION": f"{REDIS_URL}/1"}}
CELERY_BROKER_URL = f"{REDIS_URL}/0"
CELERY_RESULT_BACKEND = f"{REDIS_URL}/2"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {"hosts": [f"{REDIS_URL}/3"]},
    }
}

Building all of them from one variable means a credential change updates them together. Note that this example assumes REDIS_URL has no database number at the end.

5. ACL users and permissions

With Redis 6+ ACLs, a user can authenticate but lack permission for some commands, which gives NOPERM instead. Celery needs commands such as BRPOP, MULTI, EVAL, and pub/sub; a cache needs GET, SET, DEL, SCAN, and others. A practical ACL for an app user:

ACL SETUSER app on >s3cret ~* &* +@all -@dangerous

Restrict key patterns (~app:*) only if every component uses a prefix.

read the error codeErrorCause and fixNOAUTHno password sent; missingcolon or empty env varWRONGPASSwrong user or password;check encoding, rotationNOPERMACL user lacks commands;widen its rulesonly Celery failsbroker URL not updated;build from one varEach code points at a different layer of the setupdjango-deployment.com
Building every Redis setting from one variable prevents partial updates.

Explanation

Redis checks authentication per connection. When requirepass or ACLs are enabled, a client must send AUTH before other commands, and redis-py does that automatically when the URL contains credentials. If the URL parser finds no password, redis-py skips AUTH, and the first real command returns NOAUTH. Because Django, Celery, and Channels each create their own clients from their own settings, it is common for one to work and another to fail.

Edge cases / notes

  • Credential rotation. Managed services such as ElastiCache allow two auth tokens during rotation. Deploy the new token to every component before removing the old one.
  • Heroku-style URLs. Some providers rotate credentials and update REDIS_URL automatically; settings that copy the value into a file at build time miss the change.
  • Flower and monitoring. Separate tools need the new URL too, or they show workers as offline.

Next steps

FAQ

Why do I need a colon before the password?

In a URL, the part before the colon is the username. redis://:password@host sets an empty username and a password; without the colon, the password is read as a username.

Can I keep the password out of the URL?

django-redis accepts a separate PASSWORD option. Celery and Channels are easiest with the URL form, built from an environment variable.

What is the difference between NOAUTH and WRONGPASS?

NOAUTH means no credentials were sent. WRONGPASS means credentials were sent and rejected.

Should my Redis have a password if it is on a private network?

Yes. Private networks still contain other services that can be compromised, and managed providers often require it.

Keep going