{"record":{"id":"857f21e17b693bc0","repo":"python/cpython","slug":"invalid-address-must-be-none-or-self-address-857f21","errorCode":null,"errorMessage":"Invalid address: must be None or {self._address}","messagePattern":"Invalid address: must be None or (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/asyncio/selector_events.py","lineNumber":1279,"sourceCode":"        except (BlockingIOError, InterruptedError):\n            pass\n        except OSError as exc:\n            self._protocol.error_received(exc)\n        except (SystemExit, KeyboardInterrupt):\n            raise\n        except BaseException as exc:\n            self._fatal_error(exc, 'Fatal read error on datagram transport')\n        else:\n            self._protocol.datagram_received(data, addr)\n\n    def sendto(self, data, addr=None):\n        if not isinstance(data, (bytes, bytearray, memoryview)):\n            raise TypeError(f'data argument must be a bytes-like object, '\n                            f'not {type(data).__name__!r}')\n\n        if self._address:\n            if addr not in (None, self._address):\n                raise ValueError(\n                    f'Invalid address: must be None or {self._address}')\n            addr = self._address\n\n        if self._conn_lost and self._address:\n            if self._conn_lost >= constants.LOG_THRESHOLD_FOR_CONNLOST_WRITES:\n                logger.warning('socket.send() raised exception.')\n            self._conn_lost += 1\n            return\n\n        if not self._buffer:\n            # Attempt to send it right away first.\n            try:\n                if self._extra['peername']:\n                    self._sock.send(data)\n                else:\n                    self._sock.sendto(data, addr)\n                return\n            except (BlockingIOError, InterruptedError):","sourceCodeStart":1261,"sourceCodeEnd":1297,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/asyncio/selector_events.py#L1261-L1297","documentation":"Raised by _SelectorDatagramTransport.sendto() as ValueError when the transport was created with a fixed remote address (remote_addr=... to create_datagram_endpoint, making it 'connected') and the caller supplies an addr that is neither None nor exactly that bound address. A connected UDP socket can only talk to its designated peer, so asyncio enforces the mismatch check.","triggerScenarios":"loop.create_datagram_endpoint(protocol, remote_addr=('10.0.0.1', 9000)) then transport.sendto(data, ('10.0.0.2', 9001)); the address comparison is exact, so even an equal-meaning tuple that differs in form fails.","commonSituations":"A UDP client written to reply to the address a datagram arrived from (addr from datagram_received) instead of passing None; reusing a connected-transport code path for multiple peers; address normalization differences (e.g. '127.0.0.1' vs hostname resolution result) causing tuple mismatch.","solutions":["On a transport created with remote_addr, always send with addr=None (or the identical tuple) so it goes to the bound peer.","If you must send to arbitrary destinations, create the endpoint WITHOUT remote_addr and pass the full address each sendto().","Normalize addresses (resolve via socket.getaddrinfo) before comparing or storing the expected peer address."],"exampleFix":"// before\ntransport, _ = await loop.create_datagram_endpoint(\n    lambda: Proto(), remote_addr=('10.0.0.1', 9000))\ntransport.sendto(data, ('10.0.0.1', 9000))  # may fail if tuple form differs\n\n// after\ntransport.sendto(data)  # addr=None -> bound remote_addr\n# or, for many peers, omit remote_addr entirely:\n# transport.sendto(data, peer_addr)","handlingStrategy":"validation","validationCode":"# For a transport created with remote_addr, always send with addr=None:\ntransport.sendto(data)  # -> bound peer\n# Or normalize before comparing:\nimport socket\n\ndef same_addr(a, b):\n    ra = socket.getaddrinfo(*a[:2], type=socket.SOCK_DGRAM)[0][4]\n    rb = socket.getaddrinfo(*b[:2], type=socket.SOCK_DGRAM)[0][4]\n    return ra == rb","typeGuard":null,"tryCatchPattern":"try:\n    transport.sendto(data, addr)\nexcept ValueError as e:\n    if 'Invalid address' in str(e):\n        transport.sendto(data)  # fall back to the bound remote address\n    else:\n        raise","preventionTips":["Decide per endpoint: fixed peer -> use remote_addr and addr=None; many peers -> no remote_addr.","Never forward datagram_received's addr into sendto on a connected transport.","Store the peer tuple exactly as getaddrinfo produced it to avoid tuple mismatches."],"tags":["asyncio","networking","udp","datagram","connected-socket","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}