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.

  1. Check the host in the message; localhost:6379 in production means the default was used.
  2. Create the client with redis.from_url(REDIS_URL) and fail at startup if the variable is missing.
  3. Run r.ping() at startup so a bad URL fails the deploy, not a user request.
  4. For a cache, catch redis.exceptions.ConnectionError and fall back to the database.
  5. Set socket_connect_timeout and retry_on_timeout for flaky networks.
python
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 None

Why 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.

Plans from $29/moSee what your agent readsSee the setupCancel any time from the billing portal

Related errors

More in Databases

References: Redis docs: connect with Python (redis-py), redis-py docs: connections (from_url)