{"record":{"id":"2464e1a827c3fae3","repo":"denoland/deno","slug":"missing-content-type","errorCode":null,"errorMessage":"Missing content type","messagePattern":"Missing content type","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/22_body.js","lineNumber":472,"sourceCode":"          if (boundary === null) {\n            throw new TypeError(\n              \"Cannot turn into form data: missing boundary parameter in mime type of multipart form data\",\n            );\n          }\n          return parseFormData(chunkToU8(bytes), boundary);\n        } else if (essence === \"application/x-www-form-urlencoded\") {\n          // TODO(@AaronO): pass as-is with StringOrBuffer in op-layer\n          const entries = parseUrlEncoded(chunkToU8(bytes));\n          return formDataFromEntries(\n            ArrayPrototypeMap(\n              entries,\n              (x) => ({ name: x[0], value: x[1] }),\n            ),\n          );\n        }\n        throw new TypeError(\"Body can not be decoded as form data\");\n      }\n      throw new TypeError(\"Missing content type\");\n    }\n    case \"JSON\":\n      return JSONParse(chunkToString(bytes));\n    case \"text\":\n      return chunkToString(bytes);\n  }\n}\n\n/**\n * @param {BodyInit} object\n * @returns {{body: InnerBody, contentType: string | null}}\n */\nfunction extractBody(object) {\n  /** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */\n  let stream;\n  let source = null;\n  let length = null;\n  let contentType = null;","sourceCodeStart":454,"sourceCodeEnd":490,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/22_body.js#L454-L490","documentation":"Thrown in packageBytes() when decoding bytes as FormData and the body has no Content-Type at all (mimeType === null). Without a type, the runtime cannot decide between multipart and urlencoded decoding, so it refuses rather than guessing.","triggerScenarios":"`await res.formData()` on a Response constructed without headers: `new Response(bytes).formData()`; responses from fetch where the server sent no Content-Type header.","commonSituations":"Mock/stub responses built in tests without content-type; minimal Response construction in examples; servers omitting the header for HEAD or 204-adjacent payloads reused with formData().","solutions":["Set the content type when constructing: `new Response(bytes, { headers: { \"content-type\": \"application/x-www-form-urlencoded\" } })`.","Check `res.headers.get(\"content-type\")` first and only call formData() when it is one of the two supported types.","If you know the encoding, decode manually: new URLSearchParams(new TextDecoder().decode(bytes))."],"exampleFix":"// before\nconst res = new Response(\"a=1&b=2\");\nawait res.formData(); // Missing content type\n\n// after\nconst res = new Response(\"a=1&b=2\", {\n  headers: { \"content-type\": \"application/x-www-form-urlencoded\" },\n});\nawait res.formData();","handlingStrategy":"validation","validationCode":"const ct = res.headers.get(\"content-type\");\nif (!ct) throw new Error(\"response has no content-type; cannot parse as form data\");\nconst form = await res.formData();","typeGuard":null,"tryCatchPattern":"try { await res.formData(); } catch (e) { if (e instanceof TypeError && e.message === \"Missing content type\") { /* supply known type and decode manually */ } else throw e; }","preventionTips":["Always set a content-type header when constructing Response objects used for parsing.","Default to application/x-www-form-urlencoded in mocks when the wire format is form-encoded.","Check headers before calling formData() on third-party responses."],"tags":["form-data","content-type","fetch","response-construction"],"backgroundTag":"unsupported-content-type-parsing","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"}