{"record":{"id":"d192b41e601c86f4","repo":"python/cpython","slug":"unimplemented-ioctl-request","errorCode":null,"errorMessage":"Unimplemented ioctl request","messagePattern":"Unimplemented ioctl request","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"Platforms/emscripten/web_example_pyrepl_jspi/src.mjs","lineNumber":163,"sourceCode":"    );\n    const toWrite = Array.from(buffer.subarray(offset, offset + length));\n    PTY.write(toWrite);\n    return length;\n  },\n\n  async pollAsync(stream, timeout) {\n    if (!PTY.readable && timeout) {\n      await waitForReadable(timeout);\n    }\n    return (PTY.readable ? POLLIN : 0) | (PTY.writable ? POLLOUT : 0);\n  },\n  ioctl(stream, request, varargs) {\n    if (request === FIONREAD) {\n      const res = PTY.fromLdiscToUpperBuffer.length;\n      Module.HEAPU32[varargs / 4] = res;\n      return 0;\n    }\n    throw new Error(\"Unimplemented ioctl request\");\n  },\n};\n\nasync function setupStdio(Module) {\n  Object.assign(Module.TTY.default_tty_ops, tty_ops);\n  Object.assign(Module.TTY.stream_ops, tty_stream_ops);\n}\n\nconst emscriptenSettings = {\n  async preRun(Module) {\n    Module.addRunDependency(\"pre-run\");\n    Module.ENV.TERM = \"xterm-256color\";\n    // Uncomment next line to turn on tracing (messages go to browser console).\n    // Module.ENV.PYREPL_TRACE = \"1\";\n\n    // Leak module so we can try to show traceback if we crash on startup\n    globalThis.Module = Module;\n    await Promise.all([setupStdlib(Module), setupStdio(Module)]);","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Platforms/emscripten/web_example_pyrepl_jspi/src.mjs#L145-L181","documentation":"Raised by _ProactorBaseWritePipeTransport.sendto() when the transport was created for a fixed peer address but sendto() is called with a different non-None address. A datagram transport created with an explicit address is 'connected' to that peer, so the destination can only be None (use the bound address) or exactly the bound address. Any other value means the API is being used against its contract.","triggerScenarios":"loop.create_datagram_endpoint(protocol, remote_addr=(host, port)) then transport.sendto(data, other_addr). Also when an equal-looking address differs in normalization (e.g. ('127.0.0.1', 9999) vs an IPv6 tuple or a resolved duplicate with different family/type fields, since tuple equality includes every element).","commonSituations":"Reusing a client datagram transport to 'reply' to multiple peers (it was connected to one); DNS re-resolution producing a tuple that compares unequal to the bound one; code copied from an unconnected-socket pattern (where sendto with any address is fine) into a connected transport.","solutions":["Create the transport without remote_addr if you need to send to multiple destinations, then pass the full address on every sendto","If the transport is connected, call sendto(data) or sendto(data, None) and let it use the bound address","Cache the exact address tuple you passed to create_datagram_endpoint and reuse that object for sends","For server-style reply logic, use transport.sendto(data, addr) on a transport created with local_addr only"],"exampleFix":"# before\n_, tr = await loop.create_datagram_endpointProto, remote_addr=('127.0.0.1', 9999))\ntr.sendto(data, ('10.0.0.1', 9999))  # ValueError\n# after\n_, tr = await loop.create_datagram_endpoint(Proto, local_addr=('0.0.0.0', 0))\ntr.sendto(data, ('10.0.0.1', 9999))  # ok: unconnected transport","handlingStrategy":"validation","validationCode":"def send(tr, data, addr, bound):\n    if bound is not None and addr not in (None, bound):\n        raise ValueError(f'transport is connected to {bound}')\n    tr.sendto(data, addr)","typeGuard":null,"tryCatchPattern":"try:\n    tr.sendto(data, addr)\nexcept ValueError as e:\n    if 'Invalid address' in str(e):\n        # either use the bound peer or recreate as unconnected\n        tr.sendto(data)  # falls back to the connected address\n    else:\n        raise","preventionTips":["Create datagram transports with remote_addr only for single-peer clients","Cache the exact remote_addr tuple and reuse it verbatim","For multi-peer servers create with local_addr only and pass addr on each send","Do not re-resolve DNS per send on a connected transport"],"tags":["asyncio","udp","validation","datagram"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}