python/cpython · error · Error
Unimplemented ioctl request
Error message
Unimplemented ioctl request
What it means
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.
Source
Thrown at Platforms/emscripten/web_example_pyrepl_jspi/src.mjs:163
);
const toWrite = Array.from(buffer.subarray(offset, offset + length));
PTY.write(toWrite);
return length;
},
async pollAsync(stream, timeout) {
if (!PTY.readable && timeout) {
await waitForReadable(timeout);
}
return (PTY.readable ? POLLIN : 0) | (PTY.writable ? POLLOUT : 0);
},
ioctl(stream, request, varargs) {
if (request === FIONREAD) {
const res = PTY.fromLdiscToUpperBuffer.length;
Module.HEAPU32[varargs / 4] = res;
return 0;
}
throw new Error("Unimplemented ioctl request");
},
};
async function setupStdio(Module) {
Object.assign(Module.TTY.default_tty_ops, tty_ops);
Object.assign(Module.TTY.stream_ops, tty_stream_ops);
}
const emscriptenSettings = {
async preRun(Module) {
Module.addRunDependency("pre-run");
Module.ENV.TERM = "xterm-256color";
// Uncomment next line to turn on tracing (messages go to browser console).
// Module.ENV.PYREPL_TRACE = "1";
// Leak module so we can try to show traceback if we crash on startup
globalThis.Module = Module;
await Promise.all([setupStdlib(Module), setupStdio(Module)]);View on GitHub (pinned to bc6749cc3b)
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
Example fix
# before
_, tr = await loop.create_datagram_endpointProto, remote_addr=('127.0.0.1', 9999))
tr.sendto(data, ('10.0.0.1', 9999)) # ValueError
# after
_, tr = await loop.create_datagram_endpoint(Proto, local_addr=('0.0.0.0', 0))
tr.sendto(data, ('10.0.0.1', 9999)) # ok: unconnected transport Defensive patterns
Strategy: validation
Validate before calling
def send(tr, data, addr, bound):
if bound is not None and addr not in (None, bound):
raise ValueError(f'transport is connected to {bound}')
tr.sendto(data, addr) Try / catch
try:
tr.sendto(data, addr)
except ValueError as e:
if 'Invalid address' in str(e):
# either use the bound peer or recreate as unconnected
tr.sendto(data) # falls back to the connected address
else:
raise Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- A datagram socket was expected, got {sock!r}
- socket modifier keyword arguments can not be used when sock
- unexpected address family
- 2-tuple is expected
- data argument must be a bytes-like object, not {type(data)._
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/d192b41e601c86f4.
Report an issue: GitHub.