{"record":{"id":"0de173d566857279","repo":"denoland/deno","slug":"cannot-read-url-request-closed","errorCode":null,"errorMessage":"cannot read url: request closed","messagePattern":"cannot read url: request closed","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/23_request.js","lineNumber":166,"sourceCode":"      }\n      return this.headerListInner;\n    },\n    set headerList(value) {\n      this.headerListInner = value;\n    },\n    body,\n    redirectMode: \"follow\",\n    redirectCount: 0,\n    urlList: [typeof url === \"string\" ? () => url : url],\n    urlListProcessed: [],\n    clientRid: null,\n    blobUrlEntry,\n    url() {\n      if (this.urlListProcessed[0] === undefined) {\n        try {\n          this.urlListProcessed[0] = this.urlList[0]();\n        } catch {\n          throw new TypeError(\"cannot read url: request closed\");\n        }\n      }\n      return this.urlListProcessed[0];\n    },\n    currentUrl() {\n      const currentIndex = this.urlList.length - 1;\n      if (this.urlListProcessed[currentIndex] === undefined) {\n        try {\n          this.urlListProcessed[currentIndex] = this.urlList[currentIndex]();\n        } catch {\n          throw new TypeError(\"Cannot read url: request closed\");\n        }\n      }\n      return this.urlListProcessed[currentIndex];\n    },\n  };\n}\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/23_request.js#L148-L184","documentation":"An op-backed InnerRequest (typically a server-side Request from Deno.serve) resolves its url lazily: the url() getter calls the stored urlList callback, which performs a native read of the request's URL the first time .url is accessed. If the underlying request resource is already closed, that native call throws and is re-thrown as TypeError \"cannot read url: request closed\" (note the lowercase 'c' in this variant).","triggerScenarios":"Reading req.url on a server Request after the handler returned or after the connection/request resource was closed — e.g. inside setTimeout, a detached promise, or a background worker that received the raw request object.","commonSituations":"Async logging or metrics that reference req.url after the response is sent; request objects pushed to an in-memory job queue; event handlers attached to a server that fire after the request lifecycle ends.","solutions":["Capture const url = req.url synchronously as the first statement of the handler","Pass the captured string (not the request object) into async/background code","If you must defer the whole request, snapshot url, method, and headers up front"],"exampleFix":"// before\nDeno.serve(async (req) => {\n  await doSlowWork();\n  log(req.url); // TypeError: cannot read url: request closed\n  return new Response(\"ok\");\n});\n\n// after\nDeno.serve(async (req) => {\n  const url = req.url; // capture synchronously\n  await doSlowWork();\n  log(url);\n  return new Response(\"ok\");\n});","handlingStrategy":"try-catch","validationCode":"// No pre-check API exists — capture the string synchronously:\nfunction handle(req) {\n  const url = req.url; // materialize now; pass `url` (not `req`) onward\n  queueMicrotask(() => log(url));\n}","typeGuard":null,"tryCatchPattern":"try {\n  const url = req.url;\n} catch (err) {\n  if (err instanceof TypeError && err.message.includes(\"request closed\")) {\n    // request resource released; fall back to captured metadata\n  } else throw err;\n}","preventionTips":["Make 'capture url/method/headers first' a convention in every handler","Pass primitives (strings, arrays) into background tasks, never Request objects","In tests, keep the request alive or assert against the snapshot"],"tags":["fetch","request","url","resource-lifecycle","serve"],"backgroundTag":"use-after-close","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}