{"record":{"id":"587b0b521779411d","repo":"bitwarden/server","slug":"invalid-content","errorCode":null,"errorMessage":"Invalid content.","messagePattern":"Invalid content\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Dirt/Controllers/OrganizationReportsController.cs","lineNumber":391,"sourceCode":"    /// Uploads a report data file for a self-hosted organization report via multipart form data.\n    /// Validates the uploaded file size against the expected size (with a 1 MB leeway) and marks\n    /// the report file as validated upon success. Requires the Access Intelligence new-architecture feature flag.\n    /// </summary>\n    /// <param name=\"organizationId\">The unique identifier of the organization.</param>\n    /// <param name=\"reportId\">The unique identifier of the report to attach the file to.</param>\n    /// <param name=\"reportFileId\">The identifier of the report file entry to upload against.</param>\n    [RequireFeature(FeatureFlagKeys.AccessIntelligenceNewArchitecture)]\n    [HttpPost(\"{organizationId}/{reportId}/file\")]\n    [SelfHosted(SelfHostedOnly = true)]\n    [RequestSizeLimit(Constants.FileSize501mb)]\n    [DisableFormValueModelBinding]\n    public async Task UploadReportFileAsync(Guid organizationId, Guid reportId, [FromQuery] string reportFileId)\n    {\n        var report = await GetAuthorizedReportAsync(organizationId, reportId);\n\n        if (!Request?.ContentType?.Contains(\"multipart/\") ?? true)\n        {\n            throw new BadRequestException(\"Invalid content.\");\n        }\n\n        if (string.IsNullOrEmpty(reportFileId))\n        {\n            throw new BadRequestException(\"ReportFileId query parameter is required\");\n        }\n\n        var fileData = report.GetReportFile();\n        if (fileData == null || fileData.Id != reportFileId || fileData.Validated)\n        {\n            throw new NotFoundException();\n        }\n\n        await Request.GetFileAsync(async (stream) =>\n        {\n            await _storageService.UploadReportDataAsync(report, fileData, stream);\n        });\n","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Dirt/Controllers/OrganizationReportsController.cs#L373-L409","documentation":"Thrown by POST /reports/organizations/{organizationId}/{reportId}/file (self-hosted upload endpoint) when the request Content-Type does not contain 'multipart/'. The endpoint uses DisableFormValueModelBinding and Request.GetFileAsync to stream the multipart body, so a non-multipart request cannot be parsed. Self-hosted only.","triggerScenarios":"Client POSTs the file with Content-Type application/octet-stream, application/json, or omits Content-Type entirely instead of multipart/form-data with a proper boundary.","commonSituations":"Using HttpClient.PostAsync with raw StreamContent instead of MultipartFormDataContent; curl invocation missing -F; proxy stripping the Content-Type header or boundary; client library defaulting to JSON for binary payloads.","solutions":["Send the file as multipart/form-data: in .NET use MultipartFormDataContent; in curl use -F 'file=@path'.","Ensure the boundary parameter is present in Content-Type (most HTTP clients add it automatically when using multipart helpers).","Verify no intermediary proxy rewrites or strips the Content-Type header."],"exampleFix":"// before\nvar content = new StreamContent(fileStream); // Content-Type: application/octet-stream\nawait client.PostAsync(uploadUrl, content);\n// after\nusing var form = new MultipartFormDataContent();\nform.Add(new StreamContent(fileStream), \"file\", fileName);\nawait client.PostAsync(uploadUrl, form);","handlingStrategy":"validation","validationCode":"var contentType = httpClient.DefaultRequestHeaders; // ensure per-request content type\nif (!content.Headers.ContentType?.MediaType?.StartsWith(\"multipart/\") ?? true)\n    throw new InvalidOperationException(\"Upload must be multipart/form-data.\");","typeGuard":null,"tryCatchPattern":"try { await client.PostAsync(uploadUrl, multipartContent); }\ncatch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains(\"Invalid content\"))\n{ /* rebuild as MultipartFormDataContent and retry */ }","preventionTips":["Always use MultipartFormDataContent (or curl -F) for file uploads.","Let the HTTP client set the boundary automatically.","Verify proxies don't strip the Content-Type header."],"tags":["validation","file-upload","content-type","multipart","csharp","aspnetcore"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}