denoland/deno · error · TypeError
Missing content type
Error message
Missing content type
What it means
The null-mime branch of .formData() in ext/fetch/22_body.js: when no Content-Type header is present at all, MIME type parsing yields null and decoding form data is impossible - there is no way to pick a parser. The presence check happens after the multipart/urlencoded branches, so this fires only when the header is entirely absent (contrast with a wrong type, which is the previous error).
Source
Thrown at ext/fetch/22_body.js:472
if (boundary === null) {
throw new TypeError(
"Cannot turn into form data: missing boundary parameter in mime type of multipart form data",
);
}
return parseFormData(chunkToU8(bytes), boundary);
} else if (essence === "application/x-www-form-urlencoded") {
// TODO(@AaronO): pass as-is with StringOrBuffer in op-layer
const entries = parseUrlEncoded(chunkToU8(bytes));
return formDataFromEntries(
ArrayPrototypeMap(
entries,
(x) => ({ name: x[0], value: x[1] }),
),
);
}
throw new TypeError("Body can not be decoded as form data");
}
throw new TypeError("Missing content type");
}
case "JSON":
return JSONParse(chunkToString(bytes));
case "text":
return chunkToString(bytes);
}
}
/**
* @param {BodyInit} object
* @returns {{body: InnerBody, contentType: string | null}}
*/
function extractBody(object) {
/** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */
let stream;
let source = null;
let length = null;
let contentType = null;View on GitHub (pinned to 89f33cbef2)
Solutions
- Set an explicit Content-Type on the sending side: application/x-www-form-urlencoded for form posts
- Guard the call: read the header first and only call formData() when it exists and names a form type
- Treat a missing type defensively: reject with 400/415 rather than attempting form parsing
Example fix
// before (client)
await fetch(url, { method: "POST", body: new URLSearchParams({ a: 1 }) });
// after (client)
await fetch(url, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ a: 1 }),
}); Defensive patterns
Strategy: validation
Validate before calling
const ct = req.headers.get("content-type");
if (!ct) return new Response("content-type header required", { status: 400 });
const form = await req.formData(); Type guard
function hasContentType(res: Response | Request): boolean {
return (res.headers.get("content-type") ?? "").trim() !== "";
} Try / catch
try { return await req.formData(); } catch (e) {
if (e instanceof TypeError && e.message === "Missing content type") {
return new Response("content-type header required", { status: 400 });
}
throw e;
} Prevention
- Always send headers: { "content-type": ... } when POSTing bodies
- Check for the header before calling formData() on foreign responses
- In tests, mock fetch with realistic Content-Type headers
When it happens
Trigger: await req.formData() on a request with no Content-Type header: fetch(url, { method: "POST", body }) without a headers object, or a server response that omits the header.
Common situations: Quick fetch() POSTs where the developer forgot headers entirely; proxies (or accidental middleware) stripping the Content-Type; 3rd-party endpoints that answer 200 without any Content-Type.
Related errors
- Body can not be decoded as form data
- Cannot construct MultipartParser: multipart/form-data must p
- Cannot turn into form data: missing boundary parameter in mi
- Invalid header name: "${name}"
- Invalid header value: "${value}"
AI-assisted analysis of denoland/deno@89f33cbef2 (2026-08-16).
Data as JSON: /api/errors/2464e1a827c3fae3.
Report an issue: GitHub.