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
- Call disconnect(nowait=True) (or aclose() with the equivalent) to skip wait_closed() during shutdown.
- Raise socket_connect_timeout to give teardown more room.
- Investigate the network path (firewall idle timeouts, NAT, half-open sockets) between client and server.
- 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
- Use nowait=True during shutdown.
- Keep socket_connect_timeout reasonable for your network RTT.
- Don't block the event loop during teardown.
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
- Connection closed by server.
- Timeout writing to socket
- Timeout reading from {host_error}
- Buffer is closed.
- Error setting client name
AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04).
Data as JSON: /data/errors/efcf397892e70792.json.
Report an issue: GitHub.