bitwarden/server · warning · BadRequestException
This user has already been invited.
Error message
This user has already been invited.
What it means
Thrown as a 400 BadRequestException("This user has already been invited.") from the public/SCIM MembersController invite-import path when _inviteOrganizationUsersCommand.InviteImportedOrganizationUsersAsync returns a Failure whose Error.Message equals NoUsersToInviteError.Code ("No users to invite"). That failure means every imported member already has an existing or pending organization-user record, so there was nothing new to invite.
Source
Thrown at src/Api/AdminConsole/Public/Controllers/MembersController.cs:169
[HttpPost]
[ProducesResponseType(typeof(MemberResponseModel), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(ErrorResponseModel), (int)HttpStatusCode.BadRequest)]
public async Task<IActionResult> Post([FromBody] MemberCreateRequestModel model)
{
var hasStandaloneSecretsManager = false;
var organization = await _organizationRepository.GetByIdAsync(_currentContext.OrganizationId!.Value);
if (organization != null)
{
hasStandaloneSecretsManager = await _paymentService.HasSecretsManagerStandalone(organization);
}
var inviteRequest = model.ToInviteRequest(organization!, hasStandaloneSecretsManager, Guid.Empty, _timeProvider.GetUtcNow());
var inviteResult = await _inviteOrganizationUsersCommand.InviteImportedOrganizationUsersAsync(inviteRequest) switch
{
Success<InviteOrganizationUsersResponse> success => success,
Failure<InviteOrganizationUsersResponse> { Error.Message: NoUsersToInviteError.Code } => throw new BadRequestException("This user has already been invited."),
Failure<InviteOrganizationUsersResponse> failure => throw MapToBitException(failure.Error),
_ => throw new InvalidOperationException()
};
var user = inviteResult.Value.InvitedUsers.First();
var collections = model.Collections?.Select(c => c.ToCollectionAccessSelection()).ToList();
var response = new MemberResponseModel(user, collections);
return new JsonResult(response);
}
/// <summary>
/// Update a member.
/// </summary>
/// <remarks>
/// Updates the specified member object. If a property is not provided,
/// the value of the existing property will be reset.
/// </remarks>View on GitHub (pinned to e93b962371)
Solutions
- Before inviting, query existing organization users (GET the member list / SCIM Users with a filter on the email or externalId) and skip members already present.
- If the member was deleted, restore or reactivate the existing record instead of re-inviting.
- De-duplicate the import batch so each email/externalId appears only once.
- Treat this 400 as informational in the SCIM client (the user is already provisioned) rather than a hard failure.
Example fix
// before
await scim.createUser({ emails: [{ value: email }] });
// after
const existing = await scim.listUsers(`userName eq "${email}"`);
if (existing.totalResults === 0) {
await scim.createUser({ emails: [{ value: email }] });
} Defensive patterns
Strategy: validation
Validate before calling
async function isAlreadyMember(scim, email) {
const r = await scim.listUsers(`userName eq "${email}"`);
return (r.totalResults ?? 0) > 0;
} Type guard
function isInviteCandidate(v): v is { emails: { value: string }[] } {
return !!v && Array.isArray(v.emails) && v.emails.some(e => !!e.value);
} Try / catch
try { await scim.createUser(member); }
catch (e) {
if (e?.response?.status === 400 && /already been invited/i.test(e.response.data?.Message ?? '')) return; // already provisioned
throw e;
} Prevention
- Check existing members by email/externalId before inviting.
- De-duplicate import batches.
- Restore deleted-but-not-purged members instead of re-inviting.
- Treat 'already invited' as success in SCIM sync loops.
When it happens
Trigger: POST /scim/v2/{orgId}/users (or public members invite-import) for a single member whose email/externalId already maps to an invited or confirmed organization user. The command short-circuits with NoUsersToInviteError and the controller maps it to this 400.
Common situations: IdP/SCIM provisioning re-sends a user that is already invited or active; the member was previously deleted but not purged so the record still resolves; duplicate email in the import batch where the first occurrence consumed the invite.
Related errors
- Already accepted.
- Organization Connection configuration malformed
- Provider is already setup.
- Invalid permissions.
- User invalid.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/32c8ebcfb3b476b2.
Report an issue: GitHub.