remix-run/remix · error · MaxHeaderSizeExceededError

Exceeded maximum header size

Error message

Exceeded maximum header size

What it means

While scanning for the \r\n\r\n that terminates a part's headers, the parser buffers the pending bytes; if the buffered header region grows beyond maxHeaderSize without finding the double newline, it throws MaxHeaderSizeExceededError. This guards against unbounded memory use from header-flood or malformed parts.

Source

Thrown at packages/multipart-parser/src/lib/multipart.ts:401

          break
        }

        index += 2 // Skip \r\n after boundary

        this.#state = MultipartParserStateHeader
      }

      if (this.#state === MultipartParserStateHeader) {
        if (chunkLength - index < 4) {
          this.#buffer = chunk.subarray(index)
          break
        }

        let headerEndIndex = findDoubleNewline(chunk, index)

        if (headerEndIndex === -1) {
          if (chunkLength - index > this.maxHeaderSize) {
            throw new MaxHeaderSizeExceededError(this.maxHeaderSize)
          }

          this.#buffer = chunk.subarray(index)
          break
        }

        if (headerEndIndex - index > this.maxHeaderSize) {
          throw new MaxHeaderSizeExceededError(this.maxHeaderSize)
        }

        this.#currentHeader = chunk.subarray(index, headerEndIndex)
        this.#currentContent = []
        this.#contentLength = 0

        index = headerEndIndex + 4 // Skip header + \r\n\r\n

        this.#state = MultipartParserStateBody

View on GitHub (pinned to 9696913134)

Solutions

  1. If headers are legitimately large, pass a larger maxHeaderSize in MultipartParserOptions (default 8 KB)
  2. Audit clients for unnecessary per-part headers and trim them
  3. If unexpected, verify the boundary matches the actual body delimiters — a mismatch makes body data parse as headers

Example fix

// before
let parts = parseMultipartRequest(request) // default 8KB header limit

// after
let parts = parseMultipartRequest(request, { maxHeaderSize: 64 * 1024 })
Defensive patterns

Strategy: validation

Validate before calling

// pre-check declared header size when possible
let declared = Number(request.headers.get('Content-Length') ?? 0)
if (declared > 10 * 1024 * 1024) return new Response('Payload too large', { status: 413 })
// and parse with an explicit, adequate limit:
parseMultipartRequest(request, { maxHeaderSize: 64 * 1024 })

Try / catch

try {
  for await (let part of parseMultipartRequest(request)) { /* ... */ }
} catch (error) {
  if (error instanceof MaxHeaderSizeExceededError) {
    return new Response('Part headers too large', { status: 413 })
  }
  throw error
}

Prevention

When it happens

Trigger: A multipart part whose headers never contain \r\n\r\n within maxHeaderSize bytes — e.g. a part with thousands of header lines, extremely long single header values, or binary body data mistaken for headers after a missed boundary.

Common situations: Legitimate clients attaching very large custom headers or metadata per part; malicious header flooding; a wrong boundary causing the parser to interpret body bytes as header bytes.

Related errors


AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27). Data as JSON: /api/errors/a79460193348b4ff. Report an issue: GitHub.