denoland/deno · error · TypeError
Blob URL fetch only supports GET method
Error message
Blob URL fetch only supports GET method
What it means
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.
Source
Thrown at ext/fetch/26_fetch.js:406
// occurs. This applies to every hop, including those reached via redirects.
//
// Per https://fetch.spec.whatwg.org/#block-bad-port the check only applies
// when the URL's scheme is an HTTP(S) scheme, so https bad ports (e.g.
// https://example.com:22) are blocked too, while non-HTTP(S) schemes are
// left alone. The spec's ALPN note covers *new* protocols negotiated over
// TLS; it does not exempt https fetch from the list. This matches Node's
// undici (`requestBadPort` gates on `urlIsHttpHttpsScheme`).
const url = new URL(req.currentUrl());
if (
(url.protocol === "http:" || url.protocol === "https:") &&
url.port !== "" && BAD_PORTS[url.port] === true
) {
return networkError(`Requests to port ${url.port} are blocked`);
}
if (req.blobUrlEntry !== null) {
if (req.method !== "GET") {
throw new TypeError("Blob URL fetch only supports GET method");
}
const body = new InnerBody(req.blobUrlEntry.stream());
terminator[abortSignal.add](() => body.error(terminator.reason));
processUrlList(req.urlList, req.urlListProcessed);
return {
headerList: [
["content-length", String(req.blobUrlEntry.size)],
["content-type", req.blobUrlEntry.type],
],
status: 200,
statusMessage: "OK",
body,
type: "basic",
url() {
if (this.urlList.length == 0) return null;
return this.urlList[this.urlList.length - 1];View on GitHub (pinned to 89f33cbef2)
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
Example fix
// before
const res = await fetch(blobUrl, { method: "POST" }); // TypeError
// after
const res = await fetch(blobUrl); // GET is the only supported method
// or send the blob's data to a real endpoint:
const res2 = await fetch("https://api.example.com/upload", { method: "POST", body: blob }); Defensive patterns
Strategy: validation
Validate before calling
function assertBlobGet(url, init) {
const method = (init?.method ?? "GET").toUpperCase();
if (new URL(url).protocol === "blob:" && method !== "GET") {
throw new Error("blob: URLs only support GET; pass the Blob as a body instead");
}
}
assertBlobGet(blobUrl, init);
const res = await fetch(blobUrl, init); Type guard
function isBlobUrlGet(url: string, init?: RequestInit): boolean {
return new URL(url).protocol !== "blob:" ||
(init?.method ?? "GET").toUpperCase() === "GET";
} Try / catch
try {
const res = await fetch(url, init);
} catch (err) {
if (err instanceof TypeError && err.message.includes("Blob URL") && url.startsWith("blob:")) {
const res = await fetch(url); // retry with GET
} else throw err;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Method is not valid
- Method is forbidden
- Request with GET/HEAD method cannot have body
- Request url protocol must be 'http:' or 'https:': received '
- Request method must be GET
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/29509f21c2e735e3.
Report an issue: GitHub.