python/cpython · error · ValueError

A Stream Socket was expected, got {sock!r}

Error message

A Stream Socket was expected, got {sock!r}

What it means

Raised by create_connection's sock branch when the supplied socket is not of type SOCK_STREAM. asyncio's TCP path (and its historical AF_UNIX tolerance) requires a stream socket; datagram, raw, or packet sockets cannot back a streaming transport, so it rejects them with a ValueError naming the socket.

Source

Thrown at Lib/asyncio/base_events.py:1201

                            ', '.join(str(exc) for exc in exceptions)))
                    else:
                        # No exceptions were collected, raise a timeout error
                        raise TimeoutError('create_connection failed')
                finally:
                    exceptions = None

        else:
            if sock is None:
                raise ValueError(
                    'host and port was not specified and no sock specified')
            if sock.type != socket.SOCK_STREAM:
                # We allow AF_INET, AF_INET6, AF_UNIX as long as they
                # are SOCK_STREAM.
                # We support passing AF_UNIX sockets even though we have
                # a dedicated API for that: create_unix_connection.
                # Disallowing AF_UNIX in this method, breaks backwards
                # compatibility.
                raise ValueError(
                    f'A Stream Socket was expected, got {sock!r}')

        transport, protocol = await self._create_connection_transport(
            sock, protocol_factory, ssl, server_hostname,
            ssl_handshake_timeout=ssl_handshake_timeout,
            ssl_shutdown_timeout=ssl_shutdown_timeout)
        if self._debug:
            # Get the socket from the transport because SSL transport closes
            # the old socket and creates a new SSL socket
            sock = transport.get_extra_info('socket')
            logger.debug("%r connected to %s:%r: (%r, %r)",
                         sock, host, port, transport, protocol)
        return transport, protocol

    async def _create_connection_transport(
            self, sock, protocol_factory, ssl,
            server_hostname, server_side=False,
            ssl_handshake_timeout=None,

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Create the socket as SOCK_STREAM: socket.socket(socket.AF_INET, socket.SOCK_STREAM).
  2. For datagram needs use loop.create_datagram_endpoint instead of create_connection.
  3. For AF_UNIX streams prefer loop.create_unix_connection.

Example fix

// before
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
await loop.create_connection(proto, None, None, sock=sock)

// after
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
await loop.sock_connect(sock, addr)
transport, proto = await loop.create_connection(
    proto, None, None, sock=sock)
Defensive patterns

Strategy: type-guard

Validate before calling

if sock is not None and sock.type != socket.SOCK_STREAM:
    raise ConfigError(f'expected SOCK_STREAM, got type {sock.type}')

Type guard

import socket

def is_stream_socket(sock: socket.socket) -> bool:
    return (sock.type & socket.SOCK_STREAM) == socket.SOCK_STREAM

Prevention

When it happens

Trigger: loop.create_connection(proto, None, None, sock=s) where s was created with socket.SOCK_DGRAM or SOCK_RAW. Also sockets typed with flags that change the effective type check (e.g. SOCK_NONBLOCK is fine, but SOCK_DGRAM is not).

Common situations: Copy-pasted socket setup from a UDP code path; test doubles that fabricate sockets with the wrong type; passing a packet socket intended for a custom protocol into asyncio's stream machinery.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/529d1664c78493d7. Report an issue: GitHub.