bitwarden/server · error · NotFoundException

Resource not found.

Error message

Resource not found.

What it means

Thrown at SecretsTrashController.cs:46 inside ListByOrganizationAsync (GET secrets/{org}/trash). The first guard checks _currentContext.AccessSecretsManager(organizationId); if false the controller throws NotFoundException -> HTTP 404. The caller has no Secrets Manager access to that organization (checked before the admin check).

Solutions

  1. Ensure the caller has Secrets Manager access to the organization.
  2. Assign an SM seat to the user or use a service account provisioned under that org.
  3. Confirm the organization id is correct for this caller.

Example fix

// before: token without SM access lists trash
await client.GetAsync($"/secrets/{orgId}/trash"); // 404

// after: use an SM-enabled admin identity
var smAdminClient = ClientFor(smAdminCredential);
await smAdminClient.GetAsync($"/secrets/{orgId}/trash");
Defensive patterns

Strategy: validation

Validate before calling

if (!await HasSecretsManagerAccessAsync(orgId))
    throw new UnauthorizedAccessException("No SM access for org");
await client.GetAsync($"/secrets/{orgId}/trash");

Try / catch

try { await client.GetAsync($"/secrets/{orgId}/trash"); }
catch (ApiException ex) when (ex.StatusCode == HttpStatusCode.NotFound) { Log.Warn("No SM access; use an SM-enabled identity"); }

Prevention

When it happens

Trigger: GET /secrets/{orgId}/trash by a principal with no Secrets Manager access to the route organization.

Common situations: Standard password-manager user without an SM seat; service account from another org; SM access revoked.

Related errors


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

Appendix: source

Thrown at src/Api/SecretsManager/Controllers/SecretsTrashController.cs:46

        IEmptyTrashCommand emptyTrashCommand,
        IRestoreTrashCommand restoreTrashCommand,
        IUserService userService,
        IEventService eventService)
    {
        _currentContext = currentContext;
        _secretRepository = secretRepository;
        _emptyTrashCommand = emptyTrashCommand;
        _restoreTrashCommand = restoreTrashCommand;
        _userService = userService;
        _eventService = eventService;
    }

    [HttpGet("secrets/{organizationId}/trash")]
    public async Task<SecretWithProjectsListResponseModel> ListByOrganizationAsync(Guid organizationId)
    {
        if (!_currentContext.AccessSecretsManager(organizationId))
        {
            throw new NotFoundException();
        }

        if (!await _currentContext.OrganizationAdmin(organizationId))
        {
            throw new UnauthorizedAccessException();
        }

        var secrets = await _secretRepository.GetManyDetailsByOrganizationIdInTrashAsync(organizationId);
        return new SecretWithProjectsListResponseModel(secrets);
    }

    [HttpPost("secrets/{organizationId}/trash/empty")]
    public async Task EmptyTrashAsync(Guid organizationId, [FromBody] List<Guid> ids)
    {
        if (!_currentContext.AccessSecretsManager(organizationId))
        {
            throw new NotFoundException();
        }

View on GitHub (pinned to e93b962371)