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

  1. Let http.Server bind responses to sockets automatically instead of calling assignSocket manually
  2. Call res.detachSocket(sock) on the previous owner before assigning a new response
  3. 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

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)