Both sides - websockets 12.0 documentation
Description: What does ConnectionClosedError: no close frame received or sent mean?: If you’re seeing this traceback in the logs of a server: or if a client crashes with this traceback: it means that the TCP co...

Hide navigation sidebar
Hide table of contents sidebar
Back to top
Toggle table of contents sidebar

# Both sides

## What does `ConnectionClosedError: no close frame received or sent` mean?

If you’re seeing this traceback in the logs of a server:

    connection handler failed
    Traceback (most recent call last):
      ...
    asyncio.exceptions.IncompleteReadError: 0 bytes read on a total of 2 expected bytes

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      ...
    websockets.exceptions.ConnectionClosedError: no close frame received or sent

or if a client crashes with this traceback:

    Traceback (most recent call last):
      ...
    ConnectionResetError: [Errno 54] Connection reset by peer

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      ...
    websockets.exceptions.ConnectionClosedError: no close frame received or sent

it means that the TCP connection was lost. As a consequence, the WebSocket connection was closed without receiving and sending a close frame, which is abnormal.

You can catch and handle `ConnectionClosed` to prevent it from being logged.

There are several reasons why long-lived connections may be lost:

- End-user devices tend to lose network connectivity often and unpredictably because they can move out of wireless network coverage, get unplugged from a wired network, enter airplane mode, be put to sleep, etc.

- HTTP load balancers or proxies that aren’t configured for long-lived connections may terminate connections after a short amount of time, usually 30 seconds, despite websockets’ keepalive mechanism.

If you’re facing a reproducible issue, enable debug logs to see when and how connections are closed.

## What does `ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received` mean?

If you’re seeing this traceback in the logs of a server:

    connection handler failed
    Traceback (most recent call last):
      ...
    asyncio.exceptions.CancelledError

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      ...
    websockets.exceptions.ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received

or if a client crashes with this traceback:

    Traceback (most recent call last):
      ...
    asyncio.exceptions.CancelledError

    The above exception was the direct cause of the following exception:

    Traceback (most recent call last):
      ...
    websockets.exceptions.ConnectionClosedError: sent 1011 (internal error) keepalive ping timeout; no close frame received

it means that the WebSocket connection suffered from excessive latency and was closed after reaching the timeout of websockets’ keepalive mechanism.

You can catch and handle `ConnectionClosed` to prevent it from being logged.

There are two main reasons why latency may increase:

- Poor network connectivity.

- More traffic than the recipient can handle.

See the discussion of timeouts for details.

If websockets’ default timeout of 20 seconds is too short for your use case, you can adjust it with the `ping_timeout` argument.

## How do I set a timeout on `recv()`?

On Python ≥ 3.11, use `asyncio.timeout()`:

    async with asyncio.timeout(timeout=10):
        message = await websocket.recv()

On older versions of Python, use `asyncio.wait_for()`:

    message = await asyncio.wait_for(websocket.recv(), timeout=10)

This technique works for most APIs. When it doesn’t, for example with asynchronous context managers, websockets provides an `open_timeout` argument.

## How can I pass arguments to a custom protocol subclass?

You can bind additional arguments to the protocol factory with `functools.partial()`:

    import asyncio
    import functools
    import websockets

    class MyServerProtocol(websockets.WebSocketServerProtocol):
        def __init__(self, *args, extra_argument=None, **kwargs):
            super().__init__(*args, **kwargs)
            # do something with extra_argument

    create_protocol = functools.partial(MyServerProtocol, extra_argument=42)
    start_server = websockets.serve(..., create_protocol=create_protocol)

This example was for a server. The same pattern applies on a client.

## How do I keep idle connections open?

websockets sends pings at 20 seconds intervals to keep the connection open.

It closes the connection if it doesn’t get a pong within 20 seconds.

You can adjust this behavior with `ping_interval` and `ping_timeout`.

See Timeouts for details.

## How do I respond to pings?

If you are referring to Ping and Pong frames defined in the WebSocket protocol, don’t bother, because websockets handles them for you.

If you are connecting to a server that defines its own heartbeat at the application level, then you need to build that logic into your application.