python/cpython · error · OSError

Multiple exceptions: {}

Error message

Multiple exceptions: {}

What it means

An OSError raised by create_connection (all_errors=False path) when multiple addresses were tried and all failed with different error strings. asyncio first tries to re-raise a single exception if there was only one attempt or all messages are identical; when they differ, it joins them into one OSError whose message is 'Multiple exceptions: ...' so the user can see every failure reason.

Source

Thrown at Lib/asyncio/base_events.py:1182

                    happy_eyeballs_delay,
                    loop=self,
                ))[0]  # can't use sock, _, _ as it keeks a reference to exceptions

            if sock is None:
                exceptions = [exc for sub in exceptions for exc in sub]
                try:
                    if all_errors:
                        raise ExceptionGroup("create_connection failed", exceptions)
                    if len(exceptions) == 1:
                        raise exceptions[0]
                    elif exceptions:
                        # If they all have the same str(), raise one.
                        model = str(exceptions[0])
                        if all(str(exc) == model for exc in exceptions):
                            raise exceptions[0]
                        # Raise a combined exception so the user can see all
                        # the various error messages.
                        raise OSError('Multiple exceptions: {}'.format(
                            ', '.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.

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Parse or log the full message to see each underlying failure and fix the dominant one (often the first).
  2. Pass all_errors=True to get a structured ExceptionGroup instead of a string-joined message.
  3. Retry with backoff for transient network conditions once causes are known.

Example fix

// before
try:
    await loop.create_connection(proto, host, port)
except OSError as e:
    print(e)  # opaque 'Multiple exceptions: ...'

// after
try:
    await loop.create_connection(proto, host, port, all_errors=True)
except* OSError as eg:
    for exc in eg.exceptions:
        print(repr(exc))  # individual causes
Defensive patterns

Strategy: try-catch

Try / catch

try:
    tp, pr = await loop.create_connection(proto, host, port, all_errors=False)
except OSError as e:
    if str(e).startswith('Multiple exceptions:'):
        for part in str(e).split(', '):
            log.warning(f'connect failure: {part}')
    raise

Prevention

When it happens

Trigger: Connecting to a dual-stack host where the IPv6 attempt times out and the IPv4 attempt gets 'connection refused' — two distinct messages, so the combined OSError is raised. Only reachable with all_errors=False (pre-3.12 default).

Common situations: Partial reachability (v6 blocked, v4 refused), mixed DNS/timeout failures across multiple A records, flaky uplinks during address iteration.

Related errors


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