bitwarden/server · error · BadRequestException

One or more collections do not belong to this organization.

Error message

One or more collections do not belong to this organization.

What it means

Thrown by AccessRuleWriteValidator.ValidateCollectionsAsync (line 79) when all collections exist but at least one belongs to a different organization (c.OrganizationId != organizationId). This prevents cross-organization collection assignment to an access rule.

Source

Thrown at bitwarden_license/src/Services/Pam/Services/AccessRuleWriteValidator.cs:79

    private async Task<List<Guid>> ValidateCollectionsAsync(Guid organizationId, IEnumerable<Guid> collectionIds,
        Guid? existingRuleId)
    {
        var distinctIds = collectionIds.Distinct().ToList();
        if (distinctIds.Count == 0)
        {
            return distinctIds;
        }

        var collections = await _collectionRepository.GetManyByManyIdsAsync(distinctIds);
        if (collections.Count != distinctIds.Count)
        {
            throw new BadRequestException("One or more collections could not be found.");
        }

        if (collections.Any(c => c.OrganizationId != organizationId))
        {
            throw new BadRequestException("One or more collections do not belong to this organization.");
        }

        // Deletes clear Collection.AccessRuleId and the FK forbids dangling links, so any set link points at an
        // existing rule; only a link to a different rule is a conflict. A rule being created has no id, so for it
        // any link at all conflicts.
        if (collections.Any(c => c.AccessRuleId.HasValue && c.AccessRuleId != existingRuleId))
        {
            throw new BadRequestException("One or more collections are already governed by another access rule.");
        }

        return distinctIds;
    }
}

View on GitHub (pinned to e93b962371)

Solutions

  1. Filter collection IDs to only those belonging to the same organization before submission.
  2. Query collections by organization: _collectionRepository.GetManyByOrganizationIdAsync(orgId) and intersect with the requested IDs.
  3. Audit the API client to ensure it scopes collection lookups to the correct organizationId.

Example fix

// before — pass raw collection IDs that may span orgs
await _validator.ValidateAsync(orgId, rule, requestedCollectionIds);
// after — filter to same-org collections first
var orgCollections = await _collectionRepository.GetManyByOrganizationIdAsync(orgId);
var orgCollectionIds = orgCollections.Select(c => c.Id).ToHashSet();
var safeIds = requestedCollectionIds.Where(id => orgCollectionIds.Contains(id));
await _validator.ValidateAsync(orgId, rule, safeIds);
Defensive patterns

Strategy: validation

Validate before calling

var orgCollections = await _collectionRepository.GetManyByOrganizationIdAsync(organizationId);
var orgIds = orgCollections.Select(c => c.Id).ToHashSet();
var crossOrg = collectionIds.Where(id => !orgIds.Contains(id)).ToList();
if (crossOrg.Count > 0)
    return BadRequest($"Collections do not belong to org {organizationId}: {string.Join(", ", crossOrg)}");

Try / catch

try { await _validator.ValidateAsync(orgId, rule, collectionIds); }
catch (BadRequestException ex) when (ex.Message.Contains("do not belong"))
{ /* scope collection picker to current org */ }

Prevention

When it happens

Trigger: The collectionIds list includes one or more Collection GUIDs whose OrganizationId differs from the organizationId the access rule belongs to. The check uses collections.Any(c => c.OrganizationId != organizationId).

Common situations: Admin has access to multiple orgs and picks a collection from the wrong org; collection IDs are shared across orgs in a multi-tenant dev/staging setup; API client sends collection IDs from a different org's context.

Related errors


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