bitwarden/server · error · InvalidDataException
Missing content-type boundary.
Error message
Missing content-type boundary.
What it means
MultipartFormDataHelper.GetBoundary parses the request's Content-Type for a `boundary` parameter so it can delimit multipart/form-data parts (file uploads, e.g. Send attachments / imports). If the Content-Type carries no boundary token, the parts cannot be separated and the request fails with InvalidDataException (HTTP 400).
Source
Thrown at src/Api/Utilities/MultipartFormDataHelper.cs:130
if (ContentDispositionHeaderValue.TryParse(dataSection.ContentDisposition, out var dataContent)
&& HasFileContentDisposition(dataContent))
{
using (dataSection.Body)
{
await callback(dataSection.Body);
}
}
dataSection = null;
}
}
private static string GetBoundary(MediaTypeHeaderValue contentType, int lengthLimit)
{
var boundary = HeaderUtilities.RemoveQuotes(contentType.Boundary);
if (StringSegment.IsNullOrEmpty(boundary))
{
throw new InvalidDataException("Missing content-type boundary.");
}
if (boundary.Length > lengthLimit)
{
throw new InvalidDataException($"Multipart boundary length limit {lengthLimit} exceeded.");
}
return boundary.ToString();
}
private static bool HasFileContentDisposition(ContentDispositionHeaderValue content)
{
// Content-Disposition: form-data; name="data"; filename="Misc 002.jpg"
return content != null && content.DispositionType.Equals("form-data") &&
(!StringSegment.IsNullOrEmpty(content.FileName) || !StringSegment.IsNullOrEmpty(content.FileNameStar));
}
private static bool HasDispositionName(ContentDispositionHeaderValue content, string name)View on GitHub (pinned to e93b962371)
Solutions
- Do not set Content-Type yourself — let the HTTP client (FormData / MultipartFormDataContent) generate and append the boundary.
- If you must set it manually, append `; boundary=----YourBoundary`.
- Check that no proxy between client and server rewrites or strips the Content-Type header.
Example fix
// before
fetch(url, { method: 'POST', headers: { 'Content-Type': 'multipart/form-data' }, body: form })
// after
fetch(url, { method: 'POST', body: form }) // browser sets Content-Type + boundary Defensive patterns
Strategy: validation
Validate before calling
function assertBoundaryPresent(contentType) {
if (!/boundary=.+/i.test(contentType ?? '')) {
throw new Error('Content-Type multipart/form-data is missing a boundary; let the HTTP client set it.');
}
} Type guard
function hasMultipartBoundary(contentType: string | null | undefined): boolean {
return !!contentType && /boundary=[^;\s]+/i.test(contentType);
} Prevention
- Never hard-set Content-Type for FormData; let the browser/HttpClient generate the boundary.
- If using MultipartFormDataContent, do not override the Content-Type header manually.
- Verify proxies/gateways forward the full Content-Type unchanged.
When it happens
Trigger: A POST with header `Content-Type: multipart/form-data` but no `boundary=...` clause — typically a hand-set header that bypassed the HTTP library's boundary generation.
Common situations: Manually constructed fetch/HttpClient calls where the header is set statically; a reverse proxy or gateway stripping the boundary; using FormData but overriding its Content-Type.
Related errors
- Multipart boundary length limit {lengthLimit} exceeded.
- Invalid content.
- You cannot remove yourself.
- Organization already belongs to a provider.
- The organization is subscribed to Secrets Manager. Please co
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/90413995cb9a57e2.
Report an issue: GitHub.