aio-libs/aiohttp · error · ValueError

either both host and port or none of them are allowed

Error message

either both host and port or none of them are allowed

What it means

Raised by TCPConnector.clear_dns_cache() when the caller passes host without port (or port without host). The cache is keyed by (host, port) tuples, so partial keys are ambiguous; aiohttp refuses rather than guess. Pass both to evict one entry, or neither to flush the whole cache.

Source

Thrown at aiohttp/connector.py:1118

        return waiters

    @property
    def family(self) -> int:
        """Socket family like AF_INET."""
        return self._family

    @property
    def use_dns_cache(self) -> bool:
        """True if local DNS caching is enabled."""
        return self._use_dns_cache

    def clear_dns_cache(self, host: str | None = None, port: int | None = None) -> None:
        """Remove specified host/port or clear all dns local cache."""
        if host is not None and port is not None:
            self._cached_hosts.remove((host, port))
        elif host is not None or port is not None:
            raise ValueError("either both host and port or none of them are allowed")
        else:
            self._cached_hosts.clear()

    async def _resolve_host(
        self, host: str, port: int, traces: Sequence["Trace"] | None = None
    ) -> list[ResolveResult]:
        """Resolve host and return list of addresses."""
        if is_ip_address(host):
            # Reject legacy numeric IPv4 forms (e.g. 2130706433, 127.1) that
            # socket would map onto an address, slipping past a connector-level
            # policy that only sees the raw host.
            if ":" not in host and not is_canonical_ipv4_address(host):
                raise InvalidUrlClientError(host, "is not a canonical IPv4 address")
            return [
                {
                    "hostname": host,
                    "host": host,
                    "port": port,

View on GitHub (pinned to c0ef574e29)

Solutions

  1. Pass both: `connector.clear_dns_cache('example.com', 443)`.
  2. Or flush everything: `connector.clear_dns_cache()` with no args.

Example fix

# before
connector.clear_dns_cache(host='example.com')
# after
connector.clear_dns_cache('example.com', 443)
Defensive patterns

Strategy: validation

Validate before calling

def clear_cache(connector, host=None, port=None):
    if (host is None) != (port is None):
        raise ValueError('pass both host and port, or neither')
    if host is None:
        connector.clear_dns_cache()
    else:
        connector.clear_dns_cache(host, port)

Prevention

When it happens

Trigger: Calling `connector.clear_dns_cache(host='example.com')` or `connector.clear_dns_cache(port=443)` with the other argument omitted.

Common situations: Helper code that conditionally fills host/port and forgets the other. Tests that try to invalidate a single host but pass only the hostname. Refactor that dropped one argument by accident.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/4a809e80a070c5d5.json. Report an issue: GitHub.