bitwarden/server · error · NotFoundException
Resource not found.
Error message
Resource not found.
What it means
Thrown by PUT /{id} on GroupsController inside the per-collection ModifyGroupAccess authorization loop: if any posted collection fails AuthorizeAsync(BulkCollectionOperations.ModifyGroupAccess), the update aborts with a 404. This is distinct from the earlier org/existence 404 (132) — it fires only after the self-add guard passes and means the caller lacks manage-access on at least one collection in the save.
Source
Thrown at src/Api/AdminConsole/Controllers/GroupsController.cs:182
var currentGroupUsers = await _groupRepository.GetManyUserIdsByIdAsync(id);
// OrganizationUser may be null if the current user is a provider
if (organizationUser != null && !currentGroupUsers.Contains(organizationUser.Id) && model.Users.Contains(organizationUser.Id))
{
throw new BadRequestException("You cannot add yourself to groups.");
}
}
// Authorization check:
// You must have authorization to ModifyUserAccess for all collections being saved
var postedCollections = await _collectionRepository
.GetManyByManyIdsAsync(model.Collections.Select(c => c.Id));
foreach (var collection in postedCollections)
{
if (!(await _authorizationService.AuthorizeAsync(User, collection,
BulkCollectionOperations.ModifyGroupAccess))
.Succeeded)
{
throw new NotFoundException();
}
}
// The client only sends collections that the saving user has permissions to edit.
// We need to combine these with collections that the user doesn't have permissions for, so that we don't
// accidentally overwrite those
var currentCollections = await _collectionRepository
.GetManyByManyIdsAsync(currentAccess.Select(cas => cas.Id));
var readonlyCollectionIds = new HashSet<Guid>();
foreach (var collection in currentCollections)
{
if (!(await _authorizationService.AuthorizeAsync(User, collection, BulkCollectionOperations.ModifyGroupAccess))
.Succeeded)
{
readonlyCollectionIds.Add(collection.Id);
}
}View on GitHub (pinned to e93b962371)
Solutions
- Restrict the submitted Collections to those the caller can manage group access on; the server already preserves read-only assignments separately.
- Use an owner/admin token for cross-collection group edits.
- On 404 here (post self-add check), re-evaluate ModifyGroupAccess per collection and drop disallowed ones.
- Refresh collection rights before showing the edit form so disallowed collections are not re-submitted.
Example fix
// before
model.Collections = currentAndPostedCollections;
await api.put(`/organizations/${orgId}/groups/${id}`, model);
// after
model.Collections = currentAndPostedCollections
.Where(c => await canModifyGroupAccess(c.Id)).ToList();
await api.put(`/organizations/${orgId}/groups/${id}`, model); Defensive patterns
Strategy: validation
Validate before calling
// Restrict submitted collections to those the caller can manage group access on
model.Collections = model.Collections
.Where(c => await accessProbe.CanModifyGroupAccess(c.Id))
.ToList();
// The server preserves read-only assignments server-side, so omitting is safe Type guard
static bool CanManageAllPosted(IEnumerable<CollectionAccess> cols)
=> cols.All(c => c.CanModifyGroupAccess); Try / catch
try { await api.PutAsync($"/groups/{id}", model); }
catch (ApiException e) when (e.StatusCode == HttpStatusCode.NotFound)
{ // fired after self-add guard => permission issue, not missing group
model.Collections = await filterManageable(model.Collections); await retryOnce(); } Prevention
- Re-submit only collections the caller can manage access on; the server keeps the rest.
- Refresh collection rights before loading the edit form.
- Differentiate this 404 (post self-add check) from the existence 404.
When it happens
Trigger: Saving a group whose Collections set includes one or more collections the caller cannot grant group access to (read-only collection, cross-org collection, restricted-by-custom-role collection).
Common situations: Editor pre-loaded existing assignments that include a collection the caller lost rights to; manager editing a group that spans collections beyond their access; client sending the full current collection set back without filtering.
Related errors
- One or more collections not found.
- You cannot add yourself to groups.
- Requested collections must belong to the same organization.
- Resource not found.
- Unauthorized.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/35124df342a32a54.
Report an issue: GitHub.