redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused.
Python · updated 2026-11-04
Raised by redis-py on the first command (connections are opened lazily) when the server refuses or cannot be reached. Error 111 is "connection refused"; other numbers and messages mean timeouts or DNS failures.
Traceback (most recent call last):
File "/app/cache.py", line 18, in get_cached
value = r.get(key)
...
redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused.Quick fix
Build the client from your configured URL with redis.from_url(os.environ['REDIS_URL']) instead of redis.Redis() (which defaults to localhost:6379). Check Redis is running at that address, use the service name inside Docker, and rediss:// for hosted Redis with TLS.
- Check the host in the message; localhost:6379 in production means the default was used.
- Create the client with redis.from_url(REDIS_URL) and fail at startup if the variable is missing.
- Run r.ping() at startup so a bad URL fails the deploy, not a user request.
- For a cache, catch redis.exceptions.ConnectionError and fall back to the database.
- Set socket_connect_timeout and retry_on_timeout for flaky networks.
import os
import redis
r = redis.from_url(os.environ["REDIS_URL"], socket_connect_timeout=3)
r.ping() # fail fast at startup
def get_cached(key: str):
try:
return r.get(key)
except redis.exceptions.ConnectionError:
log.warning("redis unavailable, skipping cache")
return NoneWhy it happens
The default host in production
redis.Redis() connects to localhost:6379 unless told otherwise; code that never reads REDIS_URL works locally and fails when deployed.
Redis is not running or moved
A stopped local server, a deleted or resized managed instance, or a new hostname after a migration.
Docker networking
From inside a container, localhost is the container; use the Redis service name in the URL.
TLS or authentication required
Managed Redis often needs rediss:// and a password; plain or unauthenticated connections are refused or dropped.
Other fixes
- Celery and RQ read their own broker URL settings; check those too when the error comes from a worker.
- Use a connection pool shared across the app instead of creating clients per request.
Same error, other wording
- redis.exceptions.ConnectionError: Error -2 connecting to redis:6379. Name or service not known.
- redis.exceptions.TimeoutError: Timeout connecting to server
- kombu.exceptions.OperationalError: Error 111 connecting to localhost:6379. Connection refused.
Let your coding agent catch the next one
Runheed records this error in production with the stack trace, the breadcrumbs before it and the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:
> Find the redis ConnectionError exceptions in production, show me the host each one tried and where the client is created, and switch to redis.from_url with the configured URL and a startup ping.
Related errors
- requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.example.com'...
- pymongo.errors.ServerSelectionTimeoutError: localhost:27017: [Errno 111] Connection...
- psycopg2.OperationalError: server closed the connection unexpectedly
More in Databases
- PrismaClientKnownRequestError: Unique constraint failed on the fields: (`email`)Node.js
- PrismaClientInitializationError: Can't reach database server at `db.example.com:5432`Node.js
- MongoServerError: E11000 duplicate key error collection: app.users index: email_1 dup...Node.js
- [ioredis] Unhandled error event: Error: connect ECONNREFUSED 127.0.0.1:6379Node.js
- django.db.utils.OperationalError: no such table: orders_orderPython
- psycopg.errors.UniqueViolation: duplicate key value violates unique constraint...Python
- sqlalchemy.exc.PendingRollbackError: This Session's transaction has been rolled back due...Python
- sqlite3.OperationalError: database is lockedPython
References: Redis docs: connect with Python (redis-py), redis-py docs: connections (from_url)