python/cpython · error · TypeError

string is expected

Error message

string is expected

What it means

Raised by create_datagram_endpoint() when family is AF_UNIX but local_addr or remote_addr is not a plain string. UNIX-domain datagram addresses are filesystem paths, so both must be str (or None), unlike INET where they are (host, port) tuples.

Source

Thrown at Lib/asyncio/base_events.py:1420

                opts = dict(local_addr=local_addr, remote_addr=remote_addr,
                            family=family, proto=proto, flags=flags,
                            reuse_port=reuse_port,
                            allow_broadcast=allow_broadcast)
                problems = ', '.join(f'{k}={v}' for k, v in opts.items() if v)
                raise ValueError(
                    f'socket modifier keyword arguments can not be used '
                    f'when sock is specified. ({problems})')
            sock.setblocking(False)
            r_addr = None
        else:
            if not (local_addr or remote_addr):
                if family == 0:
                    raise ValueError('unexpected address family')
                addr_pairs_info = (((family, proto), (None, None)),)
            elif hasattr(socket, 'AF_UNIX') and family == socket.AF_UNIX:
                for addr in (local_addr, remote_addr):
                    if addr is not None and not isinstance(addr, str):
                        raise TypeError('string is expected')

                if local_addr and local_addr[0] not in (0, '\x00'):
                    try:
                        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

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Use string paths: remote_addr='/tmp/app.sock'
  2. Convert pathlib.Path with str(path) before passing
  3. Drop family=AF_UNIX if you actually meant TCP-style (host, port) addressing

Example fix

# before
await loop.create_datagram_endpoint(factory, family=socket.AF_UNIX, remote_addr=Path('/tmp/app.sock'))

# after
await loop.create_datagram_endpoint(factory, family=socket.AF_UNIX, remote_addr='/tmp/app.sock')
Defensive patterns

Strategy: type-guard

Validate before calling

if family == socket.AF_UNIX:
    local_addr = str(local_addr) if local_addr is not None else None
    remote_addr = str(remote_addr) if remote_addr is not None else None

Type guard

def is_unix_datagram_addr(a) -> TypeGuard[str | None]:
    return a is None or isinstance(a, str)

Prevention

When it happens

Trigger: loop.create_datagram_endpoint(factory, family=socket.AF_UNIX, remote_addr=('127.0.0.1', 9000)) — passing an INET-style tuple, bytes, or any non-str object as an AF_UNIX address.

Common situations: Porting INET code to UNIX sockets and leaving the tuple addresses in place; passing a pathlib.Path instead of str(path).

Related errors


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