remix-run/remix · error · MultipartParseError

Multipart boundary exceeds maximum length of ${maxBoundaryLe

Error message

Multipart boundary exceeds maximum length of ${maxBoundaryLength} characters

What it means

The MultipartParser constructor rejects boundaries longer than the RFC 2046 limit (maxBoundaryLength, 70 characters). Oversized boundaries are almost always a symptom of malformed input or a corrupted header, so construction fails fast instead of mis-parsing.

Source

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

  #findPartialTailBoundary: PartialTailSearchFunction
  #boundaryLength: number
  #boundaryBytes: Uint8Array

  #state = MultipartParserStateStart
  #buffer: Uint8Array | null = null
  #currentHeader: Uint8Array | null = null
  #currentContent: Uint8Array[] | null = null
  #contentLength = 0
  #partCount = 0
  #totalContentLength = 0

  /**
   * @param boundary The boundary string used to separate parts
   * @param options Options for the parser
   */
  constructor(boundary: string, options?: MultipartParserOptions) {
    if (boundary.length > maxBoundaryLength) {
      throw new MultipartParseError(
        `Multipart boundary exceeds maximum length of ${maxBoundaryLength} characters`,
      )
    }

    this.boundary = boundary
    this.maxHeaderSize = options?.maxHeaderSize ?? 8 * oneKb
    this.maxFileSize = options?.maxFileSize ?? 2 * oneMb
    this.maxParts = options?.maxParts ?? defaultMaxParts
    this.maxTotalSize =
      options?.maxTotalSize ?? this.maxFileSize * defaultMaxTotalSizePartAllowance + oneMb

    this.#findOpeningBoundary = createSearch(`--${boundary}`)
    this.#openingBoundaryLength = 2 + boundary.length // length of '--' + boundary
    let boundaryPattern = `\r\n--${boundary}`
    this.#findBoundary = createSearch(boundaryPattern)
    this.#findPartialTailBoundary = createPartialTailSearch(boundaryPattern)
    this.#boundaryLength = 4 + boundary.length // length of '\r\n--' + boundary
    this.#boundaryBytes = encodeAsciiPattern(boundaryPattern)

View on GitHub (pinned to 9696913134)

Solutions

  1. Reject or truncate requests whose boundary parameter exceeds 70 characters before parsing (a 4xx response is appropriate)
  2. Regenerate the boundary with a standard short random value (e.g. crypto.randomUUID() based)
  3. Fix test fixtures to use realistic boundaries

Example fix

// before
new MultipartParser('x'.repeat(200))

// after
let boundary = `----node${crypto.randomUUID()}`
new MultipartParser(boundary)
Defensive patterns

Strategy: validation

Validate before calling

const MAX_BOUNDARY = 70
if (boundary.length > MAX_BOUNDARY) {
  throw new Response(`Boundary too long (max ${MAX_BOUNDARY})`, { status: 400 })
}

Try / catch

try {
  new MultipartParser(boundary)
} catch (error) {
  if (error instanceof MultipartParseError && error.message.includes('maximum length')) {
  return new Response('Invalid multipart boundary', { status: 400 })
  }
  throw error
}

Prevention

When it happens

Trigger: new MultipartParser(boundary) where boundary.length exceeds 70 characters; or parseMultipartRequest/parseMultipartStream deriving such a boundary from a Content-Type header with a huge boundary value.

Common situations: Malicious or fuzzed requests with inflated boundary parameters; copy-paste errors embedding whitespace/base64 blobs into the boundary; hand-written test fixtures with arbitrary long delimiters.

Related errors


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