{"record":{"id":"b60a7e46229c113d","repo":"denoland/deno","slug":"body-can-not-be-decoded-as-form-data","errorCode":null,"errorMessage":"Body can not be decoded as form data","messagePattern":"Body can not be decoded as form data","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/22_body.js","lineNumber":470,"sourceCode":"        if (essence === \"multipart/form-data\") {\n          const boundary = mimeType.parameters.get(\"boundary\");\n          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;","sourceCodeStart":452,"sourceCodeEnd":488,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/fetch/22_body.js#L452-L488","documentation":"Thrown in packageBytes() when converting bytes to FormData and the body has a Content-Type, but its essence is neither multipart/form-data nor application/x-www-form-urlencoded. Only those two MIME types are decodable into FormData, so anything else (e.g. text/plain, application/json, multipart/mixed) is rejected.","triggerScenarios":"`await response.formData()` with `Content-Type: text/plain`, `application/json`, `multipart/mixed`, or `application/octet-stream`. Any non-empty, non-whitespace MIME essence that is not one of the two supported types hits this throw.","commonSituations":"Calling formData() unconditionally on API responses without checking content type; servers that answer form endpoints with JSON errors (400 application/json) — the formData() call then throws instead of surfacing the error payload.","solutions":["Branch on content type before parsing: use json() for application/json, formData() only for the two form types.","When a form endpoint returns an error response, read it as text/json according to its content type.","On the sending side, ensure uploads use multipart/form-data or application/x-www-form-urlencoded."],"exampleFix":"// before\nconst form = await res.formData(); // res is application/json error\n\n// after\nconst form = res.headers.get(\"content-type\")?.includes(\"multipart/form-data\") ||\n  res.headers.get(\"content-type\")?.includes(\"application/x-www-form-urlencoded\")\n  ? await res.formData()\n  : await res.json();","handlingStrategy":"validation","validationCode":"function formParseable(res) {\n  const ct = (res.headers.get(\"content-type\") ?? \"\").split(\";\")[0].trim().toLowerCase();\n  return ct === \"multipart/form-data\" || ct === \"application/x-www-form-urlencoded\";\n}\nconst data = formParseable(res) ? await res.formData() : await res.json();","typeGuard":null,"tryCatchPattern":"try { await res.formData(); } catch (e) { if (e instanceof TypeError && e.message === \"Body can not be decoded as form data\") { /* fall back to text()/json() based on content-type */ } else throw e; }","preventionTips":["Always branch on Content-Type before choosing a body reader.","Handle JSON error bodies from form endpoints explicitly.","Centralize response parsing in one helper that dispatches by media type."],"tags":["form-data","content-type","fetch","parsing"],"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"}