{"record":{"id":"29509f21c2e735e3","repo":"denoland/deno","slug":"blob-url-fetch-only-supports-get-method","errorCode":null,"errorMessage":"Blob URL fetch only supports GET method","messagePattern":"Blob URL fetch only supports GET method","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/26_fetch.js","lineNumber":406,"sourceCode":"  // occurs. This applies to every hop, including those reached via redirects.\n  //\n  // Per https://fetch.spec.whatwg.org/#block-bad-port the check only applies\n  // when the URL's scheme is an HTTP(S) scheme, so https bad ports (e.g.\n  // https://example.com:22) are blocked too, while non-HTTP(S) schemes are\n  // left alone. The spec's ALPN note covers *new* protocols negotiated over\n  // TLS; it does not exempt https fetch from the list. This matches Node's\n  // undici (`requestBadPort` gates on `urlIsHttpHttpsScheme`).\n  const url = new URL(req.currentUrl());\n  if (\n    (url.protocol === \"http:\" || url.protocol === \"https:\") &&\n    url.port !== \"\" && BAD_PORTS[url.port] === true\n  ) {\n    return networkError(`Requests to port ${url.port} are blocked`);\n  }\n\n  if (req.blobUrlEntry !== null) {\n    if (req.method !== \"GET\") {\n      throw new TypeError(\"Blob URL fetch only supports GET method\");\n    }\n\n    const body = new InnerBody(req.blobUrlEntry.stream());\n    terminator[abortSignal.add](() => body.error(terminator.reason));\n    processUrlList(req.urlList, req.urlListProcessed);\n\n    return {\n      headerList: [\n        [\"content-length\", String(req.blobUrlEntry.size)],\n        [\"content-type\", req.blobUrlEntry.type],\n      ],\n      status: 200,\n      statusMessage: \"OK\",\n      body,\n      type: \"basic\",\n      url() {\n        if (this.urlList.length == 0) return null;\n        return this.urlList[this.urlList.length - 1];","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/26_fetch.js#L388-L424","documentation":"blob: URLs are served internally by fetch as a synthetic 200 response built from the Blob's stream, so only GET makes sense. The main fetch path rejects any other method (POST, PUT, HEAD, etc.) with a TypeError before creating the response. Use the Blob itself as a request body if you need to send its data somewhere.","triggerScenarios":"fetch(`blob:${origin}/${uuid}`, { method: \"POST\" }) or any method other than exactly \"GET\" against a URL whose scheme is blob:, including method: \"HEAD\" and lowercase variants that do not match GET.","commonSituations":"Trying to 'upload' data via a blob: URL; HTTP clients or caching layers that rewrite the method on every request; code that always passes an explicit method string for uniformity.","solutions":["Fetch the blob: URL with GET (the default), e.g. await fetch(blobUrl)","To send blob data to a server, pass the Blob as body to an http(s) URL: fetch(url, { method: \"POST\", body: blob })","Read the underlying Blob directly instead of fetching its URL when you control the object"],"exampleFix":"// before\nconst res = await fetch(blobUrl, { method: \"POST\" }); // TypeError\n\n// after\nconst res = await fetch(blobUrl); // GET is the only supported method\n// or send the blob's data to a real endpoint:\nconst res2 = await fetch(\"https://api.example.com/upload\", { method: \"POST\", body: blob });","handlingStrategy":"validation","validationCode":"function assertBlobGet(url, init) {\n  const method = (init?.method ?? \"GET\").toUpperCase();\n  if (new URL(url).protocol === \"blob:\" && method !== \"GET\") {\n    throw new Error(\"blob: URLs only support GET; pass the Blob as a body instead\");\n  }\n}\nassertBlobGet(blobUrl, init);\nconst res = await fetch(blobUrl, init);","typeGuard":"function isBlobUrlGet(url: string, init?: RequestInit): boolean {\n  return new URL(url).protocol !== \"blob:\" ||\n    (init?.method ?? \"GET\").toUpperCase() === \"GET\";\n}","tryCatchPattern":"try {\n  const res = await fetch(url, init);\n} catch (err) {\n  if (err instanceof TypeError && err.message.includes(\"Blob URL\") && url.startsWith(\"blob:\")) {\n    const res = await fetch(url); // retry with GET\n  } else throw err;\n}","preventionTips":["Treat blob: URLs as read-only GET resources","Send blob data with fetch(httpUrl, { method, body: blob }) instead","Normalize method to uppercase before comparing with GET","Omit the method option entirely for GET requests"],"tags":["fetch","blob","url","http-method"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}