bitwarden/server · error · NotFoundException
Resource not found.
Error message
Resource not found.
What it means
Thrown by the file/renew endpoint when the report's file data is null, the reportFileId doesn't match the stored file's Id, or the file has already been Validated (no renewal needed). Reported as 404 to avoid leaking report state. Renewal only makes sense for a pending upload that hasn't been validated yet.
Source
Thrown at src/Api/Dirt/Controllers/OrganizationReportsController.cs:309
/// <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.
/// When a <c>Microsoft.Storage.BlobCreated</c> event is received, validates the uploaded
/// report file against the corresponding organization report. Orphaned blobs (with no
/// matching report) are deleted. Requires the Access Intelligence new-architecture feature flag.
/// This endpoint is anonymous to allow Azure Event Grid to call it directly.
/// </summary>
/// <returns>An <see cref="ObjectResult"/> acknowledging the Event Grid event.</returns>View on GitHub (pinned to e93b962371)
Solutions
- Use the exact reportFileId returned by create-report; do not substitute or truncate it.
- Before renewing, GET the report and check the file's Validated flag — if true, no renew is needed (use download instead).
- If GetReportFile() is null, the report has no file — recreate the report with a FileSize to start a new upload.
Example fix
// before: blind renew
var resp = await client.GetAsync(renewUrl);
// after: check state first
var report = await GetReportAsync(orgId, reportId);
var f = report.ReportFile;
if (f == null || f.Validated) return; // nothing to renew
var resp = await client.GetAsync($".../file/renew?reportFileId={f.Id}"); Defensive patterns
Strategy: validation
Validate before calling
var report = await GetReportAsync(orgId, reportId);
var f = report.ReportFile;
if (f is null || f.Id != reportFileId || f.Validated)
throw new InvalidOperationException("Report file not eligible for URL renewal."); Try / catch
try { await client.GetAsync(renewUrl); }
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{ /* file missing, id mismatch, or already validated — re-fetch report to decide */ } Prevention
- Check ReportFile.Validated before renewing; skip if true.
- Use the exact reportFileId from create-report.
- Treat 404 here as terminal unless the report state changed.
When it happens
Trigger: reportFileId in the query doesn't match report.GetReportFile().Id; the report has no file attached; the file was already validated (Validated==true) so there's nothing pending to renew.
Common situations: Client renews the wrong report's file id; upload already completed via the Event Grid webhook (cloud) or the self-hosted upload endpoint, marking Validated=true, but client retries renew; race where validation lands between create and renew.
Related errors
- Max file size is 500 MB.
- ReportFileId is required.
- Invalid content.
- ReportFileId query parameter is required
- File received does not match expected constraints.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/3545963d76434d12.
Report an issue: GitHub.