{"record":{"id":"4b9ff2113fbd2c90","repo":"bitwarden/server","slug":"the-requested-organization-already-has-a-connectio","errorCode":null,"errorMessage":"The requested organization already has a connection of type {model.Type}. Only one of each connection type may exist per organization.","messagePattern":"The requested organization already has a connection of type (.+?)\\. Only one of each connection type may exist per organization\\.","errorType":"http","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs","lineNumber":64,"sourceCode":"    }\n\n    [HttpGet(\"enabled\")]\n    public bool ConnectionsEnabled()\n    {\n        return _globalSettings.SelfHosted && _globalSettings.EnableCloudCommunication;\n    }\n\n    [HttpPost]\n    public async Task<OrganizationConnectionResponseModel> CreateConnection([FromBody] OrganizationConnectionRequestModel model)\n    {\n        if (!await HasPermissionAsync(model.OrganizationId, model.Type))\n        {\n            throw new BadRequestException($\"You do not have permission to create a connection of type {model.Type}.\");\n        }\n\n        if (await HasConnectionTypeAsync(model, null, model.Type))\n        {\n            throw new BadRequestException($\"The requested organization already has a connection of type {model.Type}. Only one of each connection type may exist per organization.\");\n        }\n\n        switch (model.Type)\n        {\n            case OrganizationConnectionType.CloudBillingSync:\n                return await CreateOrUpdateOrganizationConnectionAsync<BillingSyncConfig>(null, model, ValidateBillingSyncConfig);\n            case OrganizationConnectionType.Scim:\n                return await CreateOrUpdateOrganizationConnectionAsync<ScimConfig>(null, model);\n            default:\n                throw new BadRequestException($\"Unknown Organization connection Type: {model.Type}\");\n        }\n    }\n\n    [HttpPut(\"{organizationConnectionId}\")]\n    public async Task<OrganizationConnectionResponseModel> UpdateConnection(Guid organizationConnectionId, [FromBody] OrganizationConnectionRequestModel model)\n    {\n        if (model == null)\n        {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/AdminConsole/Controllers/OrganizationConnectionsController.cs#L46-L82","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait client.PostAsync(\"organizations/connections\", new { orgId, type, config });\n// after\nvar existing = await client.GetAsync($\"organizations/connections/{orgId}/{type}\");\nif (existing.IsSuccessStatusCode)\n    await client.PutAsync($\"organizations/connections/{existing.Id}\", body);\nelse\n    await client.PostAsync(\"organizations/connections\", body);","handlingStrategy":"validation","validationCode":"// Check for an existing connection before creating\nvar existing = await client.GetAsync<OrganizationConnectionResponseModel>(\n    $\"organizations/connections/{orgId}/{(int)type}\");\nif (existing != null) {\n    // update instead of create\n    await client.PutAsync($\"organizations/connections/{existing.Id}\", body);\n    return;\n}\nawait client.PostAsync(\"organizations/connections\", body);","typeGuard":null,"tryCatchPattern":"try { await client.PostAsync(\"organizations/connections\", body); }\ncatch (ApiException ex) when (ex.Message.Contains(\"already has a connection\")) {\n    // fetch and switch to PUT update flow\n}","preventionTips":["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."],"tags":["duplicate","organization-connections","validation","http-400"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}