python/cpython · error · TypeError
2-tuple is expected
Error message
2-tuple is expected
What it means
Raised by create_datagram_endpoint() when local_addr or remote_addr is not a 2-tuple. For INET families the address form is (host, port); passing a bare string, a 3/4-tuple, a list, or None-ish values triggers this TypeError before any name resolution.
Source
Thrown at Lib/asyncio/base_events.py:1442
if stat.S_ISSOCK(os.stat(local_addr).st_mode):
os.remove(local_addr)
except FileNotFoundError:
pass
except OSError as err:
# Directory may have permissions only to create socket.
logger.error('Unable to check or remove stale UNIX '
'socket %r: %r',
local_addr, err)
addr_pairs_info = (((family, proto),
(local_addr, remote_addr)), )
else:
# join address by (family, protocol)
addr_infos = {} # Using order preserving dict
for idx, addr in ((0, local_addr), (1, remote_addr)):
if addr is not None:
if not (isinstance(addr, tuple) and len(addr) == 2):
raise TypeError('2-tuple is expected')
infos = await self._ensure_resolved(
addr, family=family, type=socket.SOCK_DGRAM,
proto=proto, flags=flags, loop=self)
if not infos:
raise OSError('getaddrinfo() returned empty list')
for fam, _, pro, _, address in infos:
key = (fam, pro)
if key not in addr_infos:
addr_infos[key] = [None, None]
addr_infos[key][idx] = address
# each addr has to have info for each (family, proto) pair
addr_pairs_info = [
(key, addr_pair) for key, addr_pair in addr_infos.items()
if not ((local_addr and addr_pair[0] is None) or
(remote_addr and addr_pair[1] is None))]View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass exactly a 2-tuple of (host, port), e.g. ('127.0.0.1', 9999)
- If the value came from getaddrinfo(), take entry[4][0:2] or feed the original host/port instead
- Unpack config values: remote_addr=tuple(addr_pair[:2])
Example fix
# before
await loop.create_datagram_endpoint(factory, remote_addr=('127.0.0.1', 53, 0, 0))
# after
await loop.create_datagram_endpoint(factory, remote_addr=('127.0.0.1', 53)) Defensive patterns
Strategy: validation
Validate before calling
def as_addr_pair(a) -> tuple:
if not (isinstance(a, tuple) and len(a) == 2):
raise TypeError(f'expected (host, port) 2-tuple, got {a!r}')
return a
local_addr = as_addr_pair(local_addr) if local_addr else None
remote_addr = as_addr_pair(remote_addr) if remote_addr else None Type guard
def is_host_port(a: object) -> TypeGuard[tuple[str, int]]:
return isinstance(a, tuple) and len(a) == 2 and isinstance(a[0], str) and isinstance(a[1], int) Prevention
- Never feed raw getaddrinfo() results back as addresses; use the original host/port
- Parse config into (host, port) tuples once at load time
When it happens
Trigger: loop.create_datagram_endpoint(factory, remote_addr='127.0.0.1') or remote_addr=('127.0.0.1', 9000, 0, 0) or remote_addr=['127.0.0.1', 9000].
Common situations: Passing a pre-resolved getaddrinfo() 5-tuple instead of (host, port); forgetting to unpack a config pair; using a list literal instead of a tuple.
Related errors
- Unimplemented ioctl request
- A datagram socket was expected, got {sock!r}
- socket modifier keyword arguments can not be used when sock
- unexpected address family
- string is expected
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/52b7df978c049ecc.
Report an issue: GitHub.