{"record":{"id":"1cdbea2ee7e03487","repo":"bitwarden/server","slug":"reportfileid-is-required","errorCode":null,"errorMessage":"ReportFileId is required.","messagePattern":"ReportFileId is required\\.","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/Dirt/Controllers/OrganizationReportsController.cs","lineNumber":303,"sourceCode":"    /// <summary>\n    /// Renews the file upload URL for an organization report that has not yet been validated.\n    /// Returns a fresh presigned upload URL for the report file, allowing the client to retry\n    /// an upload after the original URL has expired. 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 with the pending file upload.</param>\n    /// <param name=\"reportFileId\">The identifier of the report file entry to renew the upload URL for.</param>\n    /// <returns>An <see cref=\"OrganizationReportFileResponseModel\"/> with the renewed upload URL.</returns>\n    [RequireFeature(FeatureFlagKeys.AccessIntelligenceNewArchitecture)]\n    [HttpGet(\"{organizationId}/{reportId}/file/renew\")]\n    public async Task<OrganizationReportFileResponseModel> RenewFileUploadUrlAsync(\n        Guid organizationId, Guid reportId, [FromQuery] string reportFileId)\n    {\n        var report = await GetAuthorizedReportAsync(organizationId, reportId);\n\n        if (string.IsNullOrEmpty(reportFileId))\n        {\n            throw new BadRequestException(\"ReportFileId 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        return new OrganizationReportFileResponseModel\n        {\n            ReportFileUploadUrl = await _storageService.GetReportFileUploadUrlAsync(report, fileData),\n            ReportResponse = new OrganizationReportResponseModel(report),\n            FileUploadType = _storageService.FileUploadType\n        };\n    }\n\n    /// <summary>\n    /// Handles Azure Event Grid webhook notifications for blob storage events.","sourceCodeStart":285,"sourceCodeEnd":321,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Dirt/Controllers/OrganizationReportsController.cs#L285-L321","documentation":"Thrown by GET /reports/organizations/{organizationId}/{reportId}/file/renew when the reportFileId query string parameter is missing or empty. The endpoint exists to mint a fresh presigned upload URL after the original expired; it cannot proceed without identifying which report-file entry to renew. Requires AccessIntelligenceNewArchitecture (RequireFeature attribute).","triggerScenarios":"Client calls the renew endpoint without ?reportFileId=... or with an empty value. The reportFileId comes from the original CreateOrganizationReport response's ReportFile entry.","commonSituations":"Client loses the reportFileId between create and renew (e.g. page reload without persistence); URL templating bug drops the query param; client retries renew after a failed first attempt but didn't capture the id.","solutions":["Capture and persist the reportFileId from the create-report response and pass it as ?reportFileId=<id> on renew.","If the id was lost, call GET /reports/organizations/{organizationId}/{reportId} to recover the file metadata, then renew.","Ensure URL construction includes the query parameter and is URL-encoded."],"exampleFix":"// before\nvar url = $\"/reports/organizations/{orgId}/{reportId}/file/renew\";\n// after\nvar url = $\"/reports/organizations/{orgId}/{reportId}/file/renew?reportFileId={Uri.EscapeDataString(reportFileId)}\";","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(reportFileId))\n    throw new ArgumentException(\"reportFileId is required to renew the upload URL.\", nameof(reportFileId));","typeGuard":null,"tryCatchPattern":"try { var url = $\".../file/renew?reportFileId={reportFileId}\"; await client.GetAsync(url); }\ncatch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains(\"ReportFileId\"))\n{ /* recover the id from a GET report and retry */ }","preventionTips":["Persist reportFileId immediately after create-report.","Recover lost ids via GET report before retrying renew.","Always include the query param in the URL template."],"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"}