{"record":{"id":"4a809e80a070c5d5","repo":"aio-libs/aiohttp","slug":"either-both-host-and-port-or-none-of-them-are-allo","errorCode":null,"errorMessage":"either both host and port or none of them are allowed","messagePattern":"either both host and port or none of them are allowed","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"aiohttp/connector.py","lineNumber":1118,"sourceCode":"\n        return waiters\n\n    @property\n    def family(self) -> int:\n        \"\"\"Socket family like AF_INET.\"\"\"\n        return self._family\n\n    @property\n    def use_dns_cache(self) -> bool:\n        \"\"\"True if local DNS caching is enabled.\"\"\"\n        return self._use_dns_cache\n\n    def clear_dns_cache(self, host: str | None = None, port: int | None = None) -> None:\n        \"\"\"Remove specified host/port or clear all dns local cache.\"\"\"\n        if host is not None and port is not None:\n            self._cached_hosts.remove((host, port))\n        elif host is not None or port is not None:\n            raise ValueError(\"either both host and port or none of them are allowed\")\n        else:\n            self._cached_hosts.clear()\n\n    async def _resolve_host(\n        self, host: str, port: int, traces: Sequence[\"Trace\"] | None = None\n    ) -> list[ResolveResult]:\n        \"\"\"Resolve host and return list of addresses.\"\"\"\n        if is_ip_address(host):\n            # Reject legacy numeric IPv4 forms (e.g. 2130706433, 127.1) that\n            # socket would map onto an address, slipping past a connector-level\n            # policy that only sees the raw host.\n            if \":\" not in host and not is_canonical_ipv4_address(host):\n                raise InvalidUrlClientError(host, \"is not a canonical IPv4 address\")\n            return [\n                {\n                    \"hostname\": host,\n                    \"host\": host,\n                    \"port\": port,","sourceCodeStart":1100,"sourceCodeEnd":1136,"githubUrl":"https://github.com/aio-libs/aiohttp/blob/d041d4d0fd48c3f0832084d33be16cf1c4835f85/aiohttp/connector.py#L1100-L1136","documentation":"Raised by clear_dns_cache() when exactly one of host or port is supplied. The cache is keyed by (host, port) tuples, so flushing a single host without its port (or vice versa) is ambiguous. aiohttp forces the caller to be explicit: both, to evict one entry, or neither, to wipe the cache.","triggerScenarios":"Calling connector.clear_dns_cache(host='example.com') without a port; calling clear_dns_cache(port=443) alone; looping over hosts and forgetting to pair them with ports.","commonSituations":"Building a tool that clears DNS for a service discovery refresh but only knows the hostname; refactoring that split host and port into separate config keys.","solutions":["Pass both host and port to evict a specific entry.","Pass neither (call clear_dns_cache()) to wipe the entire cache.","Carry host and port as a pair through your config so they are always flushed together.","Validate that both are non-None before calling if your inputs are optional."],"exampleFix":"# before\nconnector.clear_dns_cache(host='example.com')\n# after\nconnector.clear_dns_cache(host='example.com', port=443)\n# or wipe everything\nconnector.clear_dns_cache()","handlingStrategy":"validation","validationCode":"def clear_cache(connector, host=None, port=None):\n    if (host is None) != (port is None):\n        raise ValueError('pass both host and port, or neither')\n    if host is None:\n        connector.clear_dns_cache()\n    else:\n        connector.clear_dns_cache(host, port)","typeGuard":"null","tryCatchPattern":"try:\n    connector.clear_dns_cache(host=host, port=port)\nexcept ValueError as exc:\n    if 'either both' in str(exc):\n        connector.clear_dns_cache()  # wipe entire cache as a safe fallback\n    else:\n        raise","preventionTips":["Carry host and port as a tuple so they are always evicted together.","Prefer clear_dns_cache() (wipe all) when the specific port is unknown.","Validate cache-clear inputs at the discovery layer before reaching the connector."],"tags":["dns","connector","configuration","value-error"],"backgroundTag":null,"analyzedSha":"d041d4d0fd48c3f0832084d33be16cf1c4835f85","analyzedAt":"2026-08-11T20:44:15.550Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}