remix-run/remix · error · MultipartParseError
Invalid Content-Type header: missing boundary
Error message
Invalid Content-Type header: missing boundary
What it means
The Node parseMultipartRequest extracts the boundary from req.headers['content-type'] and throws MultipartParseError when the multipart content type has no boundary parameter. The boundary is mandatory metadata for splitting parts, so its absence is fatal.
Source
Thrown at packages/multipart-parser/src/lib/multipart.node.ts:79
* Parse a multipart Node.js request and yield each part as a {@link MultipartPart} object.
*
* @param req The Node.js `http.IncomingMessage` object containing multipart data
* @param options Options for the parser, such as `maxHeaderSize`, `maxFileSize`, `maxParts`,
* and `maxTotalSize`
* @yields Parsed {@link MultipartPart} objects from the multipart request body
* @returns An async generator yielding {@link MultipartPart} objects
*/
export async function* parseMultipartRequest(
req: http.IncomingMessage,
options?: MultipartParserOptions,
): AsyncGenerator<MultipartPart, void, unknown> {
if (!isMultipartRequest(req)) {
throw new MultipartParseError('Request is not a multipart request')
}
let boundary = getMultipartBoundary(req.headers['content-type']!)
if (!boundary) {
throw new MultipartParseError('Invalid Content-Type header: missing boundary')
}
yield* parseMultipartStream(req, {
boundary,
maxHeaderSize: options?.maxHeaderSize,
maxFileSize: options?.maxFileSize,
maxParts: options?.maxParts,
maxTotalSize: options?.maxTotalSize,
})
}
View on GitHub (pinned to 9696913134)
Solutions
- Send multipart bodies with FormData / curl -F so the boundary is generated automatically
- If setting the header manually, include the boundary and delimit the body with it
- Log and inspect req.headers['content-type'] at the server edge to catch rewrites
Example fix
# before curl -X POST http://localhost:3000/upload \ -H 'Content-Type: multipart/form-data' \ -d 'file=abc' # after curl -X POST http://localhost:3000/upload \ -F 'file=@./photo.png'
Defensive patterns
Strategy: validation
Validate before calling
let contentType = String(req.headers['content-type'] ?? '')
if (!/boundary=/i.test(contentType)) {
res.writeHead(400).end('Missing multipart boundary')
return
} Try / catch
try {
for await (let part of parseMultipartRequest(req)) { /* ... */ }
} catch (error) {
if (error instanceof MultipartParseError && error.message.includes('missing boundary')) {
res.writeHead(400).end('Content-Type must include a boundary')
return
}
throw error
} Prevention
- Never set multipart Content-Type by hand without the boundary
- Log req.headers['content-type'] at the edge to catch proxy rewrites
When it happens
Trigger: A raw Node request with Content-Type: multipart/form-data but no boundary=... — typically because a client or upstream proxy set the header manually or stripped the parameter.
Common situations: curl invocations with -H 'Content-Type: multipart/form-data' but using -d (urlencoded) instead of -F; proxies that rewrite content-type; misconfigured SDK uploads.
Related errors
- Invalid Content-Type header: missing boundary
- Request is not a multipart request
- Request is not a multipart request
- Multipart boundary exceeds maximum length of ${maxBoundaryLe
- Invalid multipart stream: missing initial boundary
AI-assisted analysis of remix-run/remix@9696913134 (2026-08-27).
Data as JSON: /api/errors/5931533ba23cc40d.
Report an issue: GitHub.