{"record":{"id":"20261412f928b6dc","repo":"bitwarden/server","slug":"reportfileid-query-parameter-is-required","errorCode":null,"errorMessage":"ReportFileId query parameter is required","messagePattern":"ReportFileId query parameter is required","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Dirt/Controllers/OrganizationReportsController.cs","lineNumber":396,"sourceCode":"    /// <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\n        var leeway = 1024L * 1024L; // 1 MB\n        var minimum = Math.Max(0, fileData.Size - leeway);\n        var maximum = Math.Min(fileData.Size + leeway, Constants.FileSize501mb);\n        var (valid, length) = await _storageService.ValidateFileAsync(report, fileData, minimum, maximum);\n        if (!valid)","sourceCodeStart":378,"sourceCodeEnd":414,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Dirt/Controllers/OrganizationReportsController.cs#L378-L414","documentation":"Thrown by the self-hosted file upload endpoint when the reportFileId query parameter is missing or empty. The controller needs to know which report-file entry to attach the uploaded bytes to; without it the upload is rejected before streaming begins.","triggerScenarios":"POST to /reports/organizations/{orgId}/{reportId}/file without ?reportFileId=...; the query param is present but empty.","commonSituations":"Client hardcodes the upload URL template without the query param; reportFileId lost between create and upload; URL-encoding bug drops the value.","solutions":["Append ?reportFileId=<id> (from the create-report response) to the upload URL.","If lost, GET the report to recover the file entry id before uploading.","Validate the query string is non-empty before issuing the POST."],"exampleFix":"// before\nvar url = $\"/reports/organizations/{orgId}/{reportId}/file\";\n// after\nvar url = $\"/reports/organizations/{orgId}/{reportId}/file?reportFileId={Uri.EscapeDataString(reportFileId)}\";","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(reportFileId))\n    throw new ArgumentException(\"reportFileId query parameter is required for upload.\", nameof(reportFileId));","typeGuard":null,"tryCatchPattern":"try { await client.PostAsync($\".../file?reportFileId={reportFileId}\", multipart); }\ncatch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains(\"ReportFileId\"))\n{ /* recover id from GET report and retry */ }","preventionTips":["Append reportFileId to the upload URL from the create response.","Recover a lost id via GET report before retrying.","Validate the query param is non-empty client-side."],"tags":["validation","file-upload","query-parameter","csharp","aspnetcore"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}