RustPython/RustPython · error · OSError
Multiple exceptions: {}
Error message
Multiple exceptions: {} What it means
OSError raised by create_connection when all_errors is False (default), more than one address was tried, and the collected exceptions have differing str() representations. asyncio collapses identical failures into one but combines distinct messages into a single OSError prefixed 'Multiple exceptions: '.
Source
Thrown at Lib/asyncio/base_events.py:1176
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 aaeab4f754)
Solutions
- Switch on exc.errno / exc.__context__ rather than parsing the combined message
- Pass all_errors=True and handle the ExceptionGroup to get each failure separately
- Constrain family= to the stack that works in your environment to reduce mixed failures
Example fix
# before
except OSError as e:
if 'refused' in str(e): ...
# after
except OSError as e:
if e.errno == errno.ECONNREFUSED: ...
# or per-attempt detail:
# await loop.create_connection(p, h, port, all_errors=True) + except* Defensive patterns
Strategy: try-catch
Try / catch
try:
tr, pr = await loop.create_connection(p, h, port)
except OSError as e:
cause = e.__context__ # often holds the first underlying error
log.warning('connect failed errno=%s cause=%r', e.errno, cause)
raise Prevention
- Branch on errno, never on formatted message strings
- Use all_errors=True when you need each attempt's failure individually
- Log e.__context__ alongside the combined OSError for diagnosis
When it happens
Trigger: loop.create_connection(proto, host, port) against a dual-stack host where the IPv6 attempt gives 'Network is unreachable' and the IPv4 attempt gives 'Connection refused'; multiple A records with different per-address failures.
Common situations: Dual-stack clients on partially IPv6-capable networks; CDN hosts with several IPs where some are filtered; retry/monitoring logic that parses exception text instead of errno.
Related errors
- no matching local address with {family=} found
- create_connection failed
- getaddrinfo() returned empty list
- staggered race failed
- Connection lost
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/4d75c6a99d35fce8.
Report an issue: GitHub.