denoland/deno · error · TypeError
Request with GET/HEAD method cannot have body
Error message
Request with GET/HEAD method cannot have body
What it means
Request constructor step 35 enforces the fetch-spec rule that GET and HEAD requests have no body. The TypeError fires when init.body is non-null, or when the input is an existing Request that already carries a body and the effective method (from init.method or the input itself) is GET/HEAD.
Solutions
- Move the data into the URL query string for GET: url.searchParams.set(...)
- Or switch the method to POST/PUT/PATCH if a body is required
- When deriving from an input request, drop its body: pass init.body: null and don't reuse the input's body
Example fix
// before
new Request("https://example.com/search", { method: "GET", body: "q=deno" }); // throws
// after
const url = new URL("https://example.com/search");
url.searchParams.set("q", "deno");
new Request(url, { method: "GET" }); Defensive patterns
Strategy: validation
Validate before calling
function buildRequest(url, method, body) {
const hasBody = body !== undefined && body !== null;
if ((method === "GET" || method === "HEAD") && hasBody) {
const u = new URL(url);
for (const [k, v] of new URLSearchParams(body)) u.searchParams.append(k, v);
return new Request(u, { method });
}
return new Request(url, { method, body });
} Type guard
function bodyAllowedForMethod(method: string, body: unknown): boolean {
const m = method.toUpperCase();
return !(m === "GET" || m === "HEAD") || body === undefined || body === null;
} Try / catch
try {
new Request(url, { method, body });
} catch (err) {
if (err instanceof TypeError && err.message.includes("GET/HEAD")) {
// move body into query params, or switch to POST — do not silently drop it
throw err;
} else throw err;
} Prevention
- Encode GET payloads as query parameters (URL.searchParams), never as body
- In generic request helpers, assert method-vs-body compatibility before constructing
- When overriding an input request's method, also drop its body explicitly
When it happens
Trigger: new Request(url, { method: "GET", body: "x=1" }); { method: "HEAD", body: formData }; new Request(existingPostRequest, { method: "GET" }) where the input request has a body.
Common situations: Toggling a POST helper to GET but keeping the body argument; generic request builders that always attach a body; wrapping an existing POST Request with a method override.
Related errors
- Body is unusable
- Input request's body is unusable
- Method is forbidden
- Method is not valid
- Blob URL fetch only supports GET method
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/85431c8502326d71.
Report an issue: GitHub.
Appendix: source
Thrown at ext/fetch/23_request.js:561
if (headerList.length !== 0) {
ArrayPrototypeSplice(headerList, 0, headerList.length);
}
fillHeaders(this[_headers], headers);
}
// 34.
let inputBody = null;
if (ObjectPrototypeIsPrototypeOf(RequestPrototype, input)) {
inputBody = input[_body];
}
// 35.
if (
(request.method === "GET" || request.method === "HEAD") &&
((init.body !== undefined && init.body !== null) ||
inputBody !== null)
) {
throw new TypeError("Request with GET/HEAD method cannot have body");
}
// 36.
let initBody = null;
// 37.
if (init.body !== undefined && init.body !== null) {
const res = extractBody(init.body);
initBody = res.body;
if (res.contentType !== null && !this[_headers].has("content-type")) {
this[_headers].append("Content-Type", res.contentType);
}
}
// 38.
const inputOrInitBody = initBody ?? inputBody;
// 40.View on GitHub (pinned to 9ad36f7a2c)