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

  1. Do not set Content-Type yourself — let the HTTP client (FormData / MultipartFormDataContent) generate and append the boundary.
  2. If you must set it manually, append `; boundary=----YourBoundary`.
  3. 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

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


AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13). Data as JSON: /api/errors/90413995cb9a57e2. Report an issue: GitHub.