bitwarden/server · error · BadRequestException
The requested organization already has a connection of type
Error message
The requested organization already has a connection of type {model.Type}. Only one of each connection type may exist per organization. What it means
Thrown by OrganizationConnectionsController.CreateConnection (POST /organizations/connections) when HasConnectionTypeAsync finds that the organization already has at least one connection of the same type. The system enforces a one-per-type-per-organization invariant, so the second POST for the same (OrganizationId, Type) pair is rejected. Maps to HTTP 400.
Source
Thrown at src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs:64
}
[HttpGet("enabled")]
public bool ConnectionsEnabled()
{
return _globalSettings.SelfHosted && _globalSettings.EnableCloudCommunication;
}
[HttpPost]
public async Task<OrganizationConnectionResponseModel> CreateConnection([FromBody] OrganizationConnectionRequestModel model)
{
if (!await HasPermissionAsync(model.OrganizationId, model.Type))
{
throw new BadRequestException($"You do not have permission to create a connection of type {model.Type}.");
}
if (await HasConnectionTypeAsync(model, null, model.Type))
{
throw new BadRequestException($"The requested organization already has a connection of type {model.Type}. Only one of each connection type may exist per organization.");
}
switch (model.Type)
{
case OrganizationConnectionType.CloudBillingSync:
return await CreateOrUpdateOrganizationConnectionAsync<BillingSyncConfig>(null, model, ValidateBillingSyncConfig);
case OrganizationConnectionType.Scim:
return await CreateOrUpdateOrganizationConnectionAsync<ScimConfig>(null, model);
default:
throw new BadRequestException($"Unknown Organization connection Type: {model.Type}");
}
}
[HttpPut("{organizationConnectionId}")]
public async Task<OrganizationConnectionResponseModel> UpdateConnection(Guid organizationConnectionId, [FromBody] OrganizationConnectionRequestModel model)
{
if (model == null)
{View on GitHub (pinned to e93b962371)
Solutions
- GET the existing connection first (GET /organizations/connections/{organizationId}/{type}) and, if present, use PUT to update it instead of POSTing a new one.
- Make the create call idempotent client-side: treat 'already has connection' as success and switch to update flow.
- Guard against duplicate submissions with a request deduplication key or disable the submit button until the first call resolves.
- If a phantom connection exists from a failed prior attempt, DELETE it before re-creating.
Example fix
// before
await client.PostAsync("organizations/connections", new { orgId, type, config });
// after
var existing = await client.GetAsync($"organizations/connections/{orgId}/{type}");
if (existing.IsSuccessStatusCode)
await client.PutAsync($"organizations/connections/{existing.Id}", body);
else
await client.PostAsync("organizations/connections", body); Defensive patterns
Strategy: validation
Validate before calling
// Check for an existing connection before creating
var existing = await client.GetAsync<OrganizationConnectionResponseModel>(
$"organizations/connections/{orgId}/{(int)type}");
if (existing != null) {
// update instead of create
await client.PutAsync($"organizations/connections/{existing.Id}", body);
return;
}
await client.PostAsync("organizations/connections", body); Try / catch
try { await client.PostAsync("organizations/connections", body); }
catch (ApiException ex) when (ex.Message.Contains("already has a connection")) {
// fetch and switch to PUT update flow
} Prevention
- Always GET-before-POST to detect an existing same-type connection.
- Make create idempotent: treat 'already exists' as a signal to update.
- Disable the submit control until the prior request completes to prevent duplicate POSTs.
When it happens
Trigger: A second POST /organizations/connections for an organization that already has a persisted connection of identical Type (e.g., a CloudBillingSync connection already exists and the client posts another; a duplicate Scim POST after the first succeeded). HasConnectionTypeAsync queries GetByOrganizationIdTypeAsync and returns true if any match exists.
Common situations: A retry-happy client re-submitting after a network timeout where the first POST actually succeeded (idempotency not implemented); two admins configuring the same connection type concurrently; a UI that does not check existing state before offering 'Create'; stale local state making the client believe no connection exists.
Related errors
- Unknown Organization connection Type: {model.Type}
- The connection type cannot be changed.
- Unknown Organization connection Type: {type}
- ExternalId cannot exceed 300 characters.
- ExternalId cannot exceed 300 characters.
AI-assisted analysis of bitwarden/server@e93b962371 (2026-08-13).
Data as JSON: /api/errors/4b9ff2113fbd2c90.
Report an issue: GitHub.