{"record":{"id":"498bba5749202638","repo":"denoland/deno","slug":"err-http2-invalid-session","errorCode":"ERR_HTTP2_INVALID_SESSION","errorMessage":"The session has been destroyed","messagePattern":"The session has been destroyed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/http2.ts","lineNumber":4152,"sourceCode":"  }\n\n  // Resets the timeout counter\n  [kUpdateTimer]() {\n    if (this.destroyed) {\n      return;\n    }\n    if (this[kTimeout]) {\n      this[kTimeout].refresh();\n      syncSessionTimeoutInspectLinks(this[kTimeout]);\n    }\n  }\n\n  // Sets the id of the next stream to be created by this Http2Session.\n  // The value must be a number in the range 0 <= n <= kMaxStreams. The\n  // value also needs to be larger than the current next stream ID.\n  setNextStreamID(id) {\n    if (this.destroyed) {\n      throw new ERR_HTTP2_INVALID_SESSION();\n    }\n\n    validateNumber(id, \"id\");\n    if (id <= 0 || id > kMaxStreams) {\n      throw new ERR_OUT_OF_RANGE(\"id\", `> 0 and <= ${kMaxStreams}`, id);\n    }\n    this[kHandle].setNextStreamID(id);\n  }\n\n  // Sets the local window size (local endpoints's window size)\n  // Returns 0 if success or throw an exception if NGHTTP2_ERR_NOMEM\n  // if the window allocation fails\n  setLocalWindowSize(windowSize) {\n    if (this.destroyed) {\n      throw new ERR_HTTP2_INVALID_SESSION();\n    }\n\n    validateInt32(windowSize, \"windowSize\", 0);","sourceCodeStart":4134,"sourceCodeEnd":4170,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/http2.ts#L4134-L4170","documentation":"Thrown by Http2Session.setNextStreamID() when the session's destroyed flag is already true. Like Node's http2 core, this polyfill refuses any method that mutates protocol state once the session is torn down, because the underlying nghttp2 handle no longer exists. setNextStreamID sets the ID of the next stream this session will create, which only has meaning on a live session.","triggerScenarios":"Calling http2session.setNextStreamID(id) after session.destroy(), after a socket 'error'/'close' event auto-destroyed the session, or from a callback/timer that fires after teardown finished.","commonSituations":"Reusing a cached or pooled ClientHttp2Session after the server closed the connection; test code that destroys the session in an afterEach hook while a pending callback still calls setNextStreamID; long-lived processes that keep one session across reconnects without checking liveness.","solutions":["Check session.destroyed (and session.closed) before calling setNextStreamID, and reconnect first if either is true","Recreate the session with http2.connect(origin) and call setNextStreamID on the fresh session before the first request()","Move the call into the session's 'connect' event handler so it always runs on a healthy session"],"exampleFix":"// before\nsession.setNextStreamID(nextId); // throws ERR_HTTP2_INVALID_SESSION if destroyed\n\n// after\nif (session.destroyed || session.closed) {\n  session = http2.connect(origin);\n}\nsession.setNextStreamID(nextId);","handlingStrategy":"validation","validationCode":"if (session.destroyed || session.closed) {\n  session = http2.connect(origin);\n}\nsession.setNextStreamID(nextId);","typeGuard":"function isSessionUsable(s) {\n  return !s.destroyed && !s.closed;\n}","tryCatchPattern":"try {\n  session.setNextStreamID(id);\n} catch (e) {\n  if (e.code === 'ERR_HTTP2_INVALID_SESSION') { session = http2.connect(origin); session.setNextStreamID(id); }\n  else throw e;\n}","preventionTips":["Treat a session as unusable the moment its 'close' event fires","Keep session creation and its initial configuration (setNextStreamID, settings) in one place so they share a lifetime","Never cache an Http2Session across reconnect cycles without a liveness check"],"tags":["http2","node-compat","session-lifecycle","deno"],"backgroundTag":"http2-session-destroyed","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}