redis/redis-py · warning · TimeoutError

Timed out closing connection after {self.socket_connect_time

Error message

Timed out closing connection after {self.socket_connect_timeout}

What it means

Raised as a TimeoutError from disconnect() when the wrapped async_timeout(socket_connect_timeout) context expires while trying to cleanly close the writer (wait_closed()). The teardown of a dead/slow socket took longer than the configured connect timeout (which is deliberately reused here as the close deadline), so the library aborts the graceful shutdown. The connection is still torn down locally; the timeout is reported so the caller knows the peer did not respond to FIN.

Source

Thrown at redis/asyncio/connection.py:1106

            async with async_timeout(self.socket_connect_timeout):
                self._parser.on_disconnect()
                # Reset the reconnect flag
                self.reset_should_reconnect()
                if not self.is_connected:
                    return
                try:
                    self._writer.close()  # type: ignore[union-attr]
                    # wait for close to finish, except when handling errors and
                    # forcefully disconnecting.
                    if not nowait:
                        await self._writer.wait_closed()  # type: ignore[union-attr]
                except OSError:
                    pass
                finally:
                    self._reader = None
                    self._writer = None
        except asyncio.TimeoutError:
            raise TimeoutError(
                f"Timed out closing connection after {self.socket_connect_timeout}"
            ) from None

        if error:
            if health_check_failed:
                close_reason = CloseReason.HEALTHCHECK_FAILED
            else:
                close_reason = CloseReason.ERROR

            if failure_count is not None and failure_count > self.retry.get_retries():
                await record_error_count(
                    server_address=getattr(self, "host", None),
                    server_port=getattr(self, "port", None),
                    network_peer_address=getattr(self, "host", None),
                    network_peer_port=getattr(self, "port", None),
                    error_type=error,
                    retry_attempts=failure_count,
                )

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Call disconnect(nowait=True) (or aclose() with the equivalent) to skip wait_closed() during shutdown.
  2. Raise socket_connect_timeout to give teardown more room.
  3. Investigate the network path (firewall idle timeouts, NAT, half-open sockets) between client and server.
  4. Ensure the event loop is not being blocked by other long-running coroutines during shutdown.

Example fix

// before
await conn.disconnect()

// after
await conn.disconnect(nowait=True)
Defensive patterns

Strategy: try-catch

Try / catch

from redis.exceptions import TimeoutError
try:
    await client.aclose()
except TimeoutError:
    await client.connection_pool.disconnect(inuse_connections=False)  # best-effort nowait

Prevention

When it happens

Trigger: Calling disconnect() (explicitly, or via pool.aclose / client.aclose / connection teardown) when self._writer.wait_closed() blocks beyond socket_connect_timeout. Common during shutdown after a network partition or when the remote is unresponsive but the TCP socket is half-open.

Common situations: Network partitions; kernel-level half-open sockets after a server crash; aggressive socket_connect_timeout values; shutting down a client under heavy load where the event loop is starved; containers/VMs where the network namespace is being torn down.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/efcf397892e70792.json. Report an issue: GitHub.