bitwarden/server · warning · NotFoundException
Resource not found.
Error message
Resource not found.
What it means
Thrown as NotFoundException (HTTP 404) by GET ~/organization/{orgId}/secrets/{id}/events when id or orgId is Guid.Empty. The very first guard rejects empty GUIDs before any data lookup, so the client never sees a difference between a missing resource and a malformed one (intentional 404-not-403 info-leak pattern).
Source
Thrown at src/Api/Dirt/Controllers/EventsController.cs:160
}
var dateRange = ApiHelpers.GetDateRange(start, end);
var result = await _eventRepository.GetManyBySendAsync(orgId, id, dateRange.Item1, dateRange.Item2,
new PageOptions { ContinuationToken = continuationToken });
var responses = result.Data.Select(e => new EventResponseModel(e));
return new ListResponseModel<EventResponseModel>(responses, result.ContinuationToken);
}
[HttpGet("~/organization/{orgId}/secrets/{id}/events")]
public async Task<ListResponseModel<EventResponseModel>> GetSecrets(
Guid id, Guid orgId,
[FromQuery] DateTime? start = null,
[FromQuery] DateTime? end = null,
[FromQuery] string continuationToken = null)
{
if (id == Guid.Empty || orgId == Guid.Empty)
{
throw new NotFoundException();
}
var secret = await _secretRepository.GetByIdAsync(id);
var orgIdForVerification = secret?.OrganizationId ?? orgId;
var secretOrg = _currentContext.GetOrganization(orgIdForVerification);
if (secretOrg == null || !await _currentContext.AccessEventLogs(secretOrg.Id))
{
throw new NotFoundException();
}
bool canViewLogs = false;
if (secret == null)
{
secret = new Core.SecretsManager.Entities.Secret { Id = id, OrganizationId = orgId };
canViewLogs = secretOrg.Type is Core.Enums.OrganizationUserType.Admin or Core.Enums.OrganizationUserType.Owner;
}View on GitHub (pinned to e93b962371)
Solutions
- Ensure the client resolves a real secret id and org id before building the URL.
- Fail fast in the client if either id equals Guid.Empty.
- Check the route template is filled completely.
Example fix
// before // GET /organization/00000000-.../secrets/00000000-.../events // // after if (orgId == Guid.Empty || secretId == Guid.Empty) return; // or show 'select a secret' await GetSecretEvents(orgId, secretId);
Defensive patterns
Strategy: validation
Validate before calling
// Reject empty GUIDs before calling secret events
if (orgId === EMPTY_GUID || secretId === EMPTY_GUID) {
throw new Error('orgId and secretId are required');
}
await getSecretEvents(orgId, secretId); Type guard
function isNonEmptyGuid(g) { return typeof g === 'string' && g !== '00000000-0000-0000-0000-000000000000'; } Prevention
- Bind both route values explicitly; never default to Guid.Empty.
- Short-circuit in the client when either id is the zero GUID.
- In tests, use real (or randomly generated) GUIDs, not Guid.Empty.
When it happens
Trigger: Calling the secret-events endpoint with id=00000000-0000-0000-0000-000000000000 or orgId=Guid.Empty, e.g. client failed to bind a route value and defaulted it.
Common situations: Client constructs the URL from an uninitialized/zero GUID; a route parameter missing in the template; integration test using Guid.Empty as a sentinel.
Related errors
- One or more collections not found.
- Resource not found.
- No version IDs provided.
- Resource not found.
- Resource not found.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/9fe7e91ba2fd990e.
Report an issue: GitHub.