redis/redis-py · error · ConnectionError

Error while reading from

Error message

Error while reading from {host_error}: {e.args}

What it means

Raised in can_read (connection.py:1389-1391) when the parser's can_read (a non-blocking poll for pending data) raises OSError. The connection is disconnected and a ConnectionError wraps the OS error args with the host:port for diagnostics. can_read is used to detect pending data or closed-connection state before/while waiting on a response.

Solutions

  1. Catch ConnectionError and reconnect (pubsub: resubscribe after reconnect; blocking call: re-issue).
  2. Enable health_check_interval and socket_keepalive to surface dead sockets earlier.
  3. Use ConnectionPool/Sentinel so broken connections are replaced transparently.
  4. After fork, always create a fresh client (the pid check in on_connect invalidates inherited fds).
  5. Inspect e.args for the underlying errno (ECONNRESET etc.) to confirm a network drop.

Example fix

# before
msg = pubsub.get_message(timeout=1)  # raises on dead socket
# after
try:
    msg = pubsub.get_message(timeout=1)
except redis.ConnectionError:
    pubsub = r.pubsub(ignore_subscribe_messages=True)
    pubsub.subscribe('ch')  # resubscribe
Defensive patterns

Strategy: try-catch

Validate before calling

# Healthy defaults for pubsub / blocking-style polling
r = redis.Redis(
    host=h, port=p,
    health_check_interval=30,
    socket_keepalive=True,
    socket_timeout=10,
)
# After fork, always create a NEW client (inherited fds are invalid)
r = redis.Redis(host=h, port=p) if os.getpid() != creation_pid else r

Type guard

null

Try / catch

from redis.exceptions import ConnectionError
def safe_get_message(pubsub, timeout=1):
    try:
        return pubsub.get_message(timeout=timeout)
    except ConnectionError:
        # reconnect + resubscribe
        pubsub = r.pubsub(ignore_subscribe_messages=True)
        pubsub.subscribe(*channels)
        return None

Prevention

When it happens

Trigger: Calling a method that polls the socket (pubsub get_message with timeout, blocking commands, cluster slot checks) on a socket that is in an error/closed state — peer reset, local close, or corrupted fd. The OSError originates in the parser's select/read of the socket.

Common situations: Pubsub connection that died while waiting for messages; blocked BLPOP/BRPOP after a silent server disconnect; cluster client polling a stale node connection; fd reuse after fork without reconnect.

Related errors


AI-assisted analysis of redis/redis-py@6a6b581b48 (2026-08-10). Data as JSON: /api/errors/eaaf6e2f240ac267. Report an issue: GitHub.

Appendix: source

Thrown at redis/connection.py:1391

            check_health=kwargs.get("check_health", True),
        )

    def can_read(self, timeout: float = 0) -> bool:
        """Poll the socket to see if there's data that can be read."""
        # TODO: Rename this API; it detects pending data or dirty/closed
        # connection state, not only whether application data can be read.
        sock = self._sock
        if not sock:
            self.connect()

        host_error = self._host_error()

        try:
            return self._parser.can_read(timeout)

        except OSError as e:
            self.disconnect()
            raise ConnectionError(f"Error while reading from {host_error}: {e.args}")

    def read_response(
        self,
        disable_decoding=False,
        *,
        timeout: Union[float, object] = SENTINEL,
        disconnect_on_error=True,
        push_request=False,
    ):
        """Read the response from a previously sent command"""

        host_error = self._host_error()

        try:
            if self.protocol in ["3", 3]:
                response = self._parser.read_response(
                    disable_decoding=disable_decoding,
                    push_request=push_request,

View on GitHub (pinned to 6a6b581b48)