{"record":{"id":"c4543b1ee70bafaa","repo":"denoland/deno","slug":"err-http2-no-socket-manipulation-c4543b","errorCode":"ERR_HTTP2_NO_SOCKET_MANIPULATION","errorMessage":"HTTP/2 sockets should not be directly manipulated (e.g. read and written)","messagePattern":"HTTP/2 sockets should not be directly manipulated \\(e\\.g\\. read and written\\)","errorType":"exception","errorClass":"NodeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/http2/compat.js","lineNumber":253,"sourceCode":"      case \"readable\": {\n        if (stream.destroyed) {\n          return false;\n        }\n        const request = stream[kRequest];\n        return request ? request.readable : stream.readable;\n      }\n      case \"setTimeout\": {\n        const session = stream.session;\n        if (session !== undefined) {\n          return FunctionPrototypeBind(session.setTimeout, session);\n        }\n        return FunctionPrototypeBind(stream.setTimeout, stream);\n      }\n      case \"write\":\n      case \"read\":\n      case \"pause\":\n      case \"resume\":\n        throw new ERR_HTTP2_NO_SOCKET_MANIPULATION();\n      default: {\n        const ref = stream.session !== undefined\n          ? stream.session[kSocket]\n          : stream;\n        const value = ref[prop];\n        return typeof value === \"function\"\n          ? FunctionPrototypeBind(value, ref)\n          : value;\n      }\n    }\n  },\n  getPrototypeOf(stream) {\n    if (stream.session !== undefined) {\n      return ReflectGetPrototypeOf(stream.session[kSocket]);\n    }\n    return ReflectGetPrototypeOf(stream);\n  },\n  set(stream, prop, value) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/http2/compat.js#L235-L271","documentation":"In http2 compat, http2Stream.socket is a Proxy that whitelists safe socket members. Reading socket.write, socket.read, socket.pause, or socket.resume throws ERR_HTTP2_NO_SOCKET_MANIPULATION: an h2 stream is multiplexed over the session's single socket, so writing or pausing it directly would corrupt other streams on the same connection. setTimeout and plain property passthrough are allowed.","triggerScenarios":"http1-style code doing req.socket.pause()/resume() for backpressure; writing raw bytes (e.g. a WebSocket upgrade handshake) through stream.socket.write(); frameworks that feature-detect socket members and accidentally touch write/read/pause/resume on the same accessor.","commonSituations":"Shared middleware serving both http1 and http2 servers; WebSocket-over-h2 attempts; ported TLS/health-check code that pokes sockets directly.","solutions":["Branch on protocol: for http1 use socket APIs, for h2 use stream/response APIs (stream.setTimeout, response.write) and never touch the socket","For pause/resume semantics use the stream's own pause()/resume() or stop reading the request stream","Use the proxy's allowed passthrough members (alpnProtocol, remoteAddress, encrypted) instead of read/write for socket introspection"],"exampleFix":"// before\nserver.on(\"request\", (req, res) => {\n  req.socket.pause(); // ERR_HTTP2_NO_SOCKET_MANIPULATION under h2\n  setTimeout(() => req.socket.resume(), 100);\n});\n\n// after\nserver.on(\"request\", (req, res) => {\n  if (!req.httpVersion.startsWith(\"2.\")) {\n    req.socket.pause();\n    setTimeout(() => req.socket.resume(), 100);\n  }\n  // h2: flow control is per-stream; do not touch the socket\n});","handlingStrategy":"type-guard","validationCode":"const isHttp2 = (req) => req.httpVersion.startsWith(\"2.\");\nif (!isHttp2(req)) {\n  req.socket.pause();\n  setTimeout(() => req.socket.resume(), 100);\n}\n// h2: operate on req.stream / response instead","typeGuard":"function isHttp2Connection(req: http.IncomingMessage): boolean {\n  return req.httpVersion.startsWith(\"2.\");\n}","tryCatchPattern":"try {\n  req.socket.pause();\n} catch (err) {\n  if (err.code === \"ERR_HTTP2_NO_SOCKET_MANIPULATION\") {\n    // h2 stream socket: use stream-level flow control (or nothing) instead\n  } else throw err;\n}","preventionTips":["Never call write/read/pause/resume on a socket you did not create","Gate socket operations behind an http1 check in dual-protocol servers","Use h2 stream/response flow control for backpressure"],"tags":["http2","socket","backpressure","node-compat"],"backgroundTag":"http2-socket-manipulation","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}