python/cpython · error · ExceptionGroup
create_connection failed
Error message
create_connection failed
What it means
The message of the ExceptionGroup raised by create_connection (Python 3.11+ with all_errors=True, or 3.12+ where all_errors defaults True) when every connection attempt failed. Each attempted address contributed one exception; asyncio groups them so the caller can inspect all root causes (DNS, refused, timeouts) rather than just the first. The group itself is an ExceptionGroup, not an OSError.
Solutions
- Catch ExceptionGroup (or use except* syntax) and inspect .exceptions for root causes.
- Pass all_errors=False to get legacy behavior (single exception or combined OSError), if compatibility matters.
- Retry at a higher level with backoff once you have logged the per-address causes.
Example fix
// before
try:
await loop.create_connection(proto, host, port)
except OSError as e: # misses ExceptionGroup on 3.12+
log(e)
// after
try:
await loop.create_connection(proto, host, port)
except* OSError as eg:
for exc in eg.exceptions:
log(f'attempt failed: {exc!r}') Defensive patterns
Strategy: try-catch
Try / catch
try:
tp, pr = await loop.create_connection(proto, host, port)
except* OSError as eg:
for exc in eg.exceptions:
log.warning(f'connect attempt failed: {exc!r}')
raise
except ExceptionGroup as eg:
for exc in eg.exceptions:
log.warning(f'connect attempt failed: {exc!r}')
raise Prevention
- On Python 3.12+, expect ExceptionGroup from create_connection and catch with except* or bare ExceptionGroup.
- Set all_errors=False explicitly if your error handling assumes OSError.
- Log eg.exceptions individually to diagnose per-address failures.
When it happens
Trigger: loop.create_connection(..., all_errors=True) to a multi-address host (dual-stack A+AAAA) where both the IPv6 and IPv4 attempts fail — e.g. firewall drops v6 (timeout) and v4 gets ECONNREFUSED. Catching OSError alone will NOT catch this ExceptionGroup.
Common situations: Upgrading to Python 3.12 where all_errors defaulted to True changed exception types; servers reachable on only one family; flaky networks where different attempts fail differently.
Related errors
- Multiple exceptions
- staggered race failed
- A Stream Socket was expected, got
- Connection lost
- getaddrinfo() returned empty list
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/bf704f16ac82a6c0.
Report an issue: GitHub.
Appendix: source
Thrown at Lib/asyncio/base_events.py:1172
else: # using happy eyeballs
sock = (await staggered.staggered_race(
(
# can't use functools.partial as it keeps a reference
# to exceptions
lambda addrinfo=addrinfo: self._connect_sock(
exceptions, addrinfo, laddr_infos
)
for addrinfo in infos
),
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:View on GitHub (pinned to bc6749cc3b)