denoland/deno · error · Error
ERR_HTTP2_SOCKET_UNBOUND
ERR_HTTP2_SOCKET_UNBOUND
Error message
The socket has been disconnected from the Http2Session
What it means
The Http2Session socket proxy's get trap allows a passthrough for properties not on the banned list, but only if session[kSocket] is still bound. Once the session is destroyed/closed the socket is detached, and reading any non-banned property (remoteAddress, writable, etc.) throws ERR_HTTP2_SOCKET_UNBOUND: 'The socket has been disconnected from the Http2Session'.
Source
Thrown at ext/node/polyfills/http2.ts:811
case "setTimeout":
case "ref":
case "unref":
return FunctionPrototypeBind(session[prop], session);
case "destroy":
case "emit":
case "end":
case "pause":
case "read":
case "resume":
case "write":
case "setEncoding":
case "setKeepAlive":
case "setNoDelay":
throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();
default: {
const socket = session[kSocket];
if (socket === undefined) {
throw new ERR_HTTP2_SOCKET_UNBOUND();
}
const value = socket[prop];
return typeof value === "function"
? FunctionPrototypeBind(value, socket)
: value;
}
}
},
getPrototypeOf(session) {
const socket = session[kSocket];
if (socket === undefined) {
throw new ERR_HTTP2_SOCKET_UNBOUND();
}
return ReflectGetPrototypeOf(socket);
},
set(session, prop, value) {
switch (prop) {
case "setTimeout":View on GitHub (pinned to 9ad36f7a2c)
Solutions
- Guard with if (!session.destroyed && !session.closed) before reading session.socket properties
- Capture the peer details (remoteAddress, remotePort) once, early in the session lifetime, and reuse the snapshot
- Register 'close' listeners that stop referencing session.socket rather than reading it
Example fix
// before
session.on('close', () => {
log(session.socket.remoteAddress); // throws ERR_HTTP2_SOCKET_UNBOUND
});
// after
const peer = session.socket.remoteAddress; // captured while bound
session.on('close', () => log(peer)); Defensive patterns
Strategy: validation
Validate before calling
const socketInfo = (session: Http2Session) =>
session.destroyed || session.closed
? undefined
: { addr: session.socket.remoteAddress, port: session.socket.remotePort }; Type guard
const hasBoundSocket = (session: Http2Session): boolean => !session.destroyed && !session.closed;
Try / catch
try {
log(session.socket.remoteAddress);
} catch (err) {
if ((err as NodeJS.ErrnoException).code === 'ERR_HTTP2_SOCKET_UNBOUND') {
// session already tore down; use a snapshot captured earlier
} else throw err;
} Prevention
- Snapshot remoteAddress/remotePort when the session opens and reuse the snapshot
- Check session.destroyed/session.closed before any session.socket access
- Do not inspect sockets inside 'close' or shutdown handlers
When it happens
Trigger: Reading session.socket.remoteAddress / remotePort / encrypted in a 'close' or shutdown handler; logging socket details inside an error handler that runs after session.destroy(); accessing session.socket properties after a GOAWAY or fatal error unbound the socket.
Common situations: Access-log or audit middleware that inspects the peer address at request end, which can race session teardown; graceful-shutdown code that iterates sessions and inspects sockets after closing them; error reporters digging into socket state post-mortem.
Related errors
- ERR_HTTP2_NO_SOCKET_MANIPULATION
- ERR_HTTP2_SOCKET_BOUND
- ERR_HTTP2_INVALID_SESSION
- ERR_HTTP2_NO_SOCKET_MANIPULATION
- ERR_FS_CP_SOCKET
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/9a0636d6718bf6ff.
Report an issue: GitHub.