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

  1. Ensure the client resolves a real secret id and org id before building the URL.
  2. Fail fast in the client if either id equals Guid.Empty.
  3. 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

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


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