{"record":{"id":"9df3de59d9f9ad9b","repo":"denoland/deno","slug":"webtransport-is-not-connected","errorCode":null,"errorMessage":"WebTransport is not connected","messagePattern":"WebTransport is not connected","errorType":"exception","errorClass":"WebTransportError","httpStatus":null,"severity":"warning","filePath":"ext/web/webtransport.js","lineNumber":332,"sourceCode":"  get anticipatedConcurrentIncomingBidirectionalStreams() {\n    webidl.assertBranded(this, WebTransportPrototype);\n    return this.#anticipatedConcurrentIncomingBidirectionalStreams;\n  }\n\n  get closed() {\n    webidl.assertBranded(this, WebTransportPrototype);\n    return this.#closed.promise;\n  }\n\n  close(closeInfo) {\n    webidl.assertBranded(this, WebTransportPrototype);\n    closeInfo = webidl.converters.WebTransportCloseInfo(\n      closeInfo,\n      \"Failed to execute 'close' on 'WebTransport'\",\n      \"Argument 1\",\n    );\n    if (!this.#conn) {\n      throw new WebTransportError(\"WebTransport is not connected\", {\n        source: \"session\",\n      });\n    }\n    this.#conn.close({\n      closeCode: closeInfo.closeCode,\n      reason: closeInfo.reason,\n    });\n  }\n\n  get datagrams() {\n    webidl.assertBranded(this, WebTransportPrototype);\n    return this.#datagrams;\n  }\n\n  async createBidirectionalStream(options) {\n    webidl.assertBranded(this, WebTransportPrototype);\n    options = webidl.converters.WebTransportSendStreamOptions(\n      options,","sourceCodeStart":314,"sourceCodeEnd":350,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/web/webtransport.js#L314-L350","documentation":"WebTransport.close() requires an established session; if close() is called before the connection op completed, the internal connection handle is still unset and Deno throws a WebTransportError (source: \"session\") from ext/web/webtransport.js. This typically happens in cleanup code that runs immediately after constructing the transport or right after a failed connection.","triggerScenarios":"const wt = new WebTransport(url); wt.close(); on adjacent lines; finally-block cleanup racing the not-yet-settled connection; error handling that closes the session before awaiting ready; close() after the connection already failed.","commonSituations":"try/finally wrappers that always close; timeouts firing before connection completes; UI unmount handlers closing a transport that never connected; aborting a page/component during connection.","solutions":["Await `wt.ready` before closing, or track connection state yourself.","Wrap close() in try/catch and ignore WebTransportError when the session never connected.","In cleanup paths, use `wt.closed.catch(() => {})` to observe termination without throwing.","Cancel pending work via your own AbortController rather than closing an unconnected session."],"exampleFix":"// before\nconst wt = new WebTransport(url);\ndoWork().finally(() => wt.close()); // may throw before connect\n\n// after\nconst wt = new WebTransport(url);\ntry {\n  await wt.ready;\n  await doWork();\n} finally {\n  try { wt.close({}); } catch { /* not connected */ }\n}","handlingStrategy":"try-catch","validationCode":"let connected = false;\nconst wt = new WebTransport(url);\nawait wt.ready.then(() => { connected = true; });\nfunction closeIfConnected() {\n  if (connected) wt.close({});\n}","typeGuard":"function isNotConnectedError(e) {\n  return e.name === \"WebTransportError\" &&\n    e.message === \"WebTransport is not connected\";\n}","tryCatchPattern":"try {\n  wt.close({ closeCode: 0, reason: \"done\" });\n} catch (e) {\n  if (!(e.name === \"WebTransportError\" && e.message === \"WebTransport is not connected\")) throw e;\n}","preventionTips":["Await ready before registering cleanup handlers that call close().","Make close() idempotent in your wrapper and swallow the not-connected error.","Watch wt.closed to detect termination instead of polling close()."],"tags":["webtransport","lifecycle","cleanup","web-api"],"backgroundTag":"close-before-connect","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}