{"record":{"id":"5dcdf9a9a5e6c7e0","repo":"denoland/deno","slug":"multipart-part-headers-are-too-large","errorCode":null,"errorMessage":"Multipart part headers are too large","messagePattern":"Multipart part headers are too large","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/21_formdata.js","lineNumber":512,"sourceCode":"    let headerText = \"\";\n    let headerStart = 0;\n    let state = 0;\n    let fileStart = 0;\n\n    for (let i = 0; i < this.body.length; i++) {\n      const byte = this.body[i];\n      const prevByte = this.body[i - 1];\n      const isNewLine = byte === LF && prevByte === CR;\n\n      if (state === 0 && isNewLine) {\n        state = 1;\n        headerStart = i + 1;\n      } else if (\n        state === 1\n      ) {\n        const headerByteLength = i - headerStart + 1;\n        if (headerByteLength > MAX_MULTIPART_PART_HEADER_SIZE) {\n          throw new TypeError(\"Multipart part headers are too large\");\n        }\n        if (\n          isNewLine && this.body[i + 1] === CR &&\n          this.body[i + 2] === LF\n        ) {\n          // end of the headers section\n          headerText = decodeLatin1Bytes(\n            TypedArrayPrototypeSubarray(this.body, headerStart, i + 1),\n          );\n          state = 2;\n          fileStart = i + 3; // After \\r\\n\n        }\n      } else if (state === 2) {\n        if (isNewLine) {\n          const delimiterType = this.#delimiterType(i + 1);\n          if (delimiterType === 0) {\n            continue;\n          }","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/21_formdata.js#L494-L530","documentation":"A size hardening limit in MultipartParser.parseBody(): while scanning state 1 (the header section of a part), the byte span from headerStart to the current position must stay <= MAX_MULTIPART_PART_HEADER_SIZE = 16 * 1024 (line 391). A part whose headers (including a giant Content-Disposition) exceed 16 KiB throws this TypeError; so does a malformed body whose \\r\\n\\r\\n header terminator never arrives, letting body bytes be miscounted as headers until the cap hits.","triggerScenarios":"A part with an extremely long Content-Disposition filename; many headers totalling >16 KiB; a body missing the CRLFCRLF separator so headers never terminate.","commonSituations":"Uploads of files with very long names packed into Content-Disposition; clients that stuff JSON metadata into custom part headers; hostile payloads in security tests probing parser limits.","solutions":["Keep part headers small - filenames shorter, metadata in form fields, not headers","On the receive side, wrap formData() in try/catch and translate this TypeError into a 413/400 response","If generating multipart manually, verify each part emits a proper \\r\\n\\r\\n after its header block"],"exampleFix":"// before (sender)\npartHeaders.set(\"content-disposition\", `form-data; name=\"f\"; filename=\"${rawName}\"`);\n\n// after (sender)\nconst safeName = rawName.replaceAll(/[\"\\r\\n]/g, \"_\").slice(0, 255);\npartHeaders.set(\"content-disposition\", `form-data; name=\"f\"; filename=\"${safeName}\"`);","handlingStrategy":"try-catch","validationCode":"// sender side: bound header-block size before emitting a part\nconst headerBlock = partHeaderLines.join(\"\\r\\n\");\nif (headerBlock.length > 16 * 1024) {\n  throw new Error(\"part headers exceed 16 KiB; shorten filenames / drop metadata\");\n}","typeGuard":null,"tryCatchPattern":"try { return await req.formData(); } catch (e) {\n  if (e instanceof TypeError && e.message.includes(\"headers are too large\")) {\n    return new Response(\"part headers too large\", { status: 413 });\n  }\n  throw e;\n}","preventionTips":["Sanitize uploaded filenames (strip quotes/CRLF, cap length ~255)","Keep part metadata out of headers; 16 KiB per part is the hard ceiling","Ensure every generated part ends its header block with \\r\\n\\r\\n"],"tags":["fetch","form-data","multipart","limits"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}