calcom/cal.diy · warning · HttpError
Bad Request (Invalid Multi Form Data)
Error message
Bad Request (Invalid Multi Form Data)
What it means
Thrown by parseMultiFormData (HttpError, HTTP 400) when req.formData() rejects for a multipart/form-data request. A log.error records the exception and path. It signals the multipart payload was malformed or unreadable.
Source
Thrown at apps/web/app/api/parseRequestData.ts:26
export async function parseUrlFormData(req: NextRequest): Promise<Record<string, any>> {
try {
// Read raw text body (because Next.js does NOT parse x-www-form-urlencoded automatically)
const rawBody = await req.text();
const params = new URLSearchParams(rawBody);
return Object.fromEntries(params);
} catch (e) {
log.error(`Invalid Url Form Data: ${e} from path ${req.nextUrl}`);
throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid Url Form Data)" });
}
}
export async function parseMultiFormData(req: NextRequest): Promise<Record<string, any>> {
try {
const formData = await req.formData();
return Object.fromEntries(formData.entries());
} catch (e) {
log.error(`Invalid Multi Form Data: ${e} from path ${req.nextUrl}`);
throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid Multi Form Data)" });
}
}
export async function parseRequestData(req: NextRequest): Promise<Record<string, any>> {
const contentType = req.headers.get("content-type") ?? "application/json";
if (contentType.includes("application/json")) {
try {
return await req.json();
} catch (e) {
log.error(`Invalid JSON: ${e} from path ${req.nextUrl}`);
throw new HttpError({ statusCode: 400, message: "Bad Request (Invalid JSON)" });
}
}
if (contentType.includes("application/x-www-form-urlencoded")) {
return await parseUrlFormData(req);
}
View on GitHub (pinned to 176037d0af)
Solutions
- Use a FormData object on the client so the browser sets a correct boundary automatically.
- Confirm no middleware reads the body before parseMultiFormData; Next.js route handlers own the body stream.
- Raise server body-size limits if large uploads are expected, and verify the proxy preserves the multipart boundary.
- Log the underlying error to distinguish boundary issues from stream-consumption issues.
Example fix
// before
await fetch('/api/upload', {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data; boundary=...' }, // hand-rolled
body: rawBody,
});
// after
const fd = new FormData();
fd.append('file', fileInput.files[0]);
await fetch('/api/upload', { method: 'POST', body: fd }); // browser sets boundary Defensive patterns
Strategy: try-catch
Validate before calling
// Let the browser build the multipart body
const fd = new FormData();
fd.append('file', file);
await fetch('/api/upload', { method: 'POST', body: fd }); // browser sets boundary Type guard
function looksLikeMultipartContentType(ct: string): boolean {
return /^multipart\/form-data;\s*boundary=.+/.test(ct);
} Try / catch
try {
await parseMultiFormData(req);
} catch (e) {
if (e instanceof HttpError && e.statusCode === 400) {
return Response.json({ error: 'Malformed multipart upload' }, { status: 400 });
}
throw e;
} Prevention
- Never set the multipart Content-Type/boundary manually; let FormData do it.
- Raise body-size limits for expected large uploads.
- Ensure the body stream is read exactly once in the route handler.
When it happens
Trigger: POST with Content-Type multipart/form-data whose body is missing/corrupted: no boundary, truncated chunks, oversized field, or the body stream was already consumed.
Common situations: Missing or incorrect multipart boundary, client abort mid-upload, request body already read by body-parser middleware, reverse proxy stripping the boundary.
Related errors
- Bad Request (Invalid Url Form Data)
- Bad Request (Invalid JSON)
- Unsupported Content-Type. Expected ${contentType}
- ApiKeysService -Cannot set both apiKeyDaysValid and apiKeyNe
- teamId is required for team events, please provide a valid t
AI-assisted analysis of calcom/cal.diy@176037d0af (2026-08-12).
Data as JSON: /api/errors/eba7c335eee11ee3.
Report an issue: GitHub.