denoland/deno · error · Error
ERR_HTTP_SOCKET_ASSIGNED
ERR_HTTP_SOCKET_ASSIGNED
Error message
ServerResponse has an already assigned socket
What it means
ERR_HTTP_SOCKET_ASSIGNED from ServerResponse.assignSocket(): a socket may be bound to at most one active ServerResponse, tracked as socket._httpMessage. Calling res.assignSocket(sock) when sock._httpMessage is already set — the socket still serves another response — throws, preventing two responses from interleaving writes on one connection.
Solutions
- Let http.Server bind responses to sockets automatically instead of calling assignSocket manually
- Call res.detachSocket(sock) on the previous owner before assigning a new response
- Guard the assignment: check sock._httpMessage === undefined before res.assignSocket(sock)
Example fix
// before res2.assignSocket(sock); // sock._httpMessage still set by res1 -> throws // after res1.detachSocket(sock); res2.assignSocket(sock);
Defensive patterns
Strategy: type-guard
Validate before calling
if (sock._httpMessage !== undefined) {
sock._httpMessage.detachSocket(sock); // release the previous owner first
}
res.assignSocket(sock); Type guard
const isSocketFree = (sock) => sock._httpMessage === undefined;
Try / catch
try {
res.assignSocket(sock);
} catch (e) {
if (e.code === 'ERR_HTTP_SOCKET_ASSIGNED') {
// socket already bound; detach previous owner or pick another socket
sock._httpMessage?.detachSocket(sock);
res.assignSocket(sock);
} else throw e;
} Prevention
- Treat socket._httpMessage as internal state; prefer the server's own response lifecycle
- Pair every assignSocket with an eventual detachSocket
- In tests, create a fresh socket per response instead of reusing one
When it happens
Trigger: Calling res.assignSocket(sock) twice for the same pair; binding a response to a socket grabbed from a live server 'connection' event that another response owns; manually driving ServerResponse the way http.Server does internally.
Common situations: Custom HTTP frameworks or test harnesses that construct and bind ServerResponse by hand; interposition layers on connection events; socket-management code ported between Node/Deno versions where lifecycle details differ.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/f32d445f9a15e0d0.
Report an issue: GitHub.
Appendix: source
Thrown at ext/node/polyfills/_http_server.js:384
response: this,
});
}
}
ObjectSetPrototypeOf(ServerResponse.prototype, OutgoingMessage.prototype);
ObjectSetPrototypeOf(ServerResponse, OutgoingMessage);
ServerResponse.prototype.statusCode = 200;
ServerResponse.prototype.statusMessage = undefined;
function onServerResponseClose() {
if (this._httpMessage) {
emitCloseNT(this._httpMessage);
}
}
ServerResponse.prototype.assignSocket = function assignSocket(socket) {
if (socket._httpMessage) {
throw new ERR_HTTP_SOCKET_ASSIGNED();
}
socket._httpMessage = this;
if (socket._parent) {
socket._parent._httpMessage = this;
socket._parent._httpMessageDetached = false;
}
socket.on("close", onServerResponseClose);
this.socket = socket;
this.emit("socket", socket);
this._flush();
};
ServerResponse.prototype.detachSocket = function detachSocket(socket) {
assert(socket._httpMessage === this);
socket.removeListener("close", onServerResponseClose);
socket._httpMessage = null;
socket._httpMessageDetached = true;
if (socket._parent) {View on GitHub (pinned to 9ad36f7a2c)