bitwarden/server · error · BadRequestException

ReportFileId is required.

Error message

ReportFileId is required.

What it means

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).

Source

Thrown at src/Api/Dirt/Controllers/OrganizationReportsController.cs:303

    /// <summary>
    /// Renews the file upload URL for an organization report that has not yet been validated.
    /// Returns a fresh presigned upload URL for the report file, allowing the client to retry
    /// an upload after the original URL has expired. Requires the Access Intelligence new-architecture feature flag.
    /// </summary>
    /// <param name="organizationId">The unique identifier of the organization.</param>
    /// <param name="reportId">The unique identifier of the report with the pending file upload.</param>
    /// <param name="reportFileId">The identifier of the report file entry to renew the upload URL for.</param>
    /// <returns>An <see cref="OrganizationReportFileResponseModel"/> with the renewed upload URL.</returns>
    [RequireFeature(FeatureFlagKeys.AccessIntelligenceNewArchitecture)]
    [HttpGet("{organizationId}/{reportId}/file/renew")]
    public async Task<OrganizationReportFileResponseModel> RenewFileUploadUrlAsync(
        Guid organizationId, Guid reportId, [FromQuery] string reportFileId)
    {
        var report = await GetAuthorizedReportAsync(organizationId, reportId);

        if (string.IsNullOrEmpty(reportFileId))
        {
            throw new BadRequestException("ReportFileId is required.");
        }

        var fileData = report.GetReportFile();
        if (fileData == null || fileData.Id != reportFileId || fileData.Validated)
        {
            throw new NotFoundException();
        }

        return new OrganizationReportFileResponseModel
        {
            ReportFileUploadUrl = await _storageService.GetReportFileUploadUrlAsync(report, fileData),
            ReportResponse = new OrganizationReportResponseModel(report),
            FileUploadType = _storageService.FileUploadType
        };
    }

    /// <summary>
    /// Handles Azure Event Grid webhook notifications for blob storage events.

View on GitHub (pinned to e93b962371)

Solutions

  1. Capture and persist the reportFileId from the create-report response and pass it as ?reportFileId=<id> on renew.
  2. If the id was lost, call GET /reports/organizations/{organizationId}/{reportId} to recover the file metadata, then renew.
  3. Ensure URL construction includes the query parameter and is URL-encoded.

Example fix

// before
var url = $"/reports/organizations/{orgId}/{reportId}/file/renew";
// after
var url = $"/reports/organizations/{orgId}/{reportId}/file/renew?reportFileId={Uri.EscapeDataString(reportFileId)}";
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(reportFileId))
    throw new ArgumentException("reportFileId is required to renew the upload URL.", nameof(reportFileId));

Try / catch

try { var url = $".../file/renew?reportFileId={reportFileId}"; await client.GetAsync(url); }
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.BadRequest && ex.Message.Contains("ReportFileId"))
{ /* recover the id from a GET report and retry */ }

Prevention

When it happens

Trigger: Client calls the renew endpoint without ?reportFileId=... or with an empty value. The reportFileId comes from the original CreateOrganizationReport response's ReportFile entry.

Common situations: 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.

Related errors


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