{"record":{"id":"840e2c6c31355e9d","repo":"bitwarden/server","slug":"there-already-exists-a-slack-integration-for-this","errorCode":null,"errorMessage":"There already exists a Slack integration for this organization","messagePattern":"There already exists a Slack integration for this organization","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"warning","filePath":"src/Api/Dirt/Controllers/SlackIntegrationController.cs","lineNumber":58,"sourceCode":"        }\n\n        var integrations = await integrationRepository.GetManyByOrganizationAsync(organizationId);\n        var integration = integrations.FirstOrDefault(i => i.Type == IntegrationType.Slack);\n\n        if (integration is null)\n        {\n            // No slack integration exists, create Initiated version\n            integration = await integrationRepository.CreateAsync(new OrganizationIntegration\n            {\n                OrganizationId = organizationId,\n                Type = IntegrationType.Slack,\n                Configuration = null,\n            });\n        }\n        else if (integration.Configuration is not null)\n        {\n            // A Completed (fully configured) Slack integration already exists, throw to prevent overriding\n            throw new BadRequestException(\"There already exists a Slack integration for this organization\");\n\n        } // An Initiated slack integration exits, re-use it and kick off a new OAuth flow\n\n        var state = IntegrationOAuthState.FromIntegration(integration, timeProvider);\n        var redirectUrl = slackService.GetRedirectUrl(\n            callbackUrl: callbackUrl,\n            state: state.ToString()\n        );\n\n        if (string.IsNullOrEmpty(redirectUrl))\n        {\n            throw new NotFoundException();\n        }\n\n        return Redirect(redirectUrl);\n    }\n\n    [HttpGet(\"integrations/slack/create\", Name = \"SlackIntegration_Create\")]","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/bitwarden/server/blob/e93b962371d80964556f5590c6615f5160a437a1/src/Api/Dirt/Controllers/SlackIntegrationController.cs#L40-L76","documentation":"Thrown during Slack OAuth initiation when a Slack integration already exists for the organization AND has a non-null Configuration (meaning it is fully configured/completed). The controller prevents overriding an existing completed integration. BadRequestException returns HTTP 400.","triggerScenarios":"Initiating a new Slack OAuth flow for an org that already has a completed Slack integration (Configuration is not null). The flow allows re-using an 'Initiated' (Configuration == null) integration but blocks overriding a 'Completed' one.","commonSituations":"Re-running the Slack setup wizard for an org that already finished configuration; duplicate setup attempts by different admins; a previous integration was set up and the user wants to reconfigure without first deleting the old one.","solutions":["Delete the existing completed Slack integration for the organization before initiating a new OAuth flow.","Provide a UI check that disables the 'Connect Slack' button when a completed integration already exists.","If reconfiguration is legitimately needed, implement a delete-then-recreate workflow."],"exampleFix":"// before\nawait api.InitiateSlackOAuthAsync(orgId); // throws if already configured\n\n// after\nvar existing = await api.GetSlackIntegrationAsync(orgId);\nif (existing?.Configuration != null)\n{\n    await api.DeleteSlackIntegrationAsync(orgId);\n}\nawait api.InitiateSlackOAuthAsync(orgId);","handlingStrategy":"validation","validationCode":"// Check for existing completed integration before initiating\nvar integrations = await integrationRepository.GetManyByOrganizationAsync(orgId);\nvar existing = integrations.FirstOrDefault(i => i.Type == IntegrationType.Slack);\nif (existing?.Configuration != null)\n    return Conflict(\"A completed Slack integration already exists. Delete it first to reconfigure.\");\n// safe to initiate","typeGuard":"public static bool HasCompletedSlackIntegration(IEnumerable<OrganizationIntegration> integrations) =>\n    integrations.Any(i => i.Type == IntegrationType.Slack && i.Configuration != null);","tryCatchPattern":"try\n{\n    await _slackService.InitiateOAuthAsync(orgId);\n}\ncatch (BadRequestException ex) when (ex.Message.Contains(\"already exists\"))\n{\n    return Conflict(ex.Message);\n}","preventionTips":["Check the integration list before showing the 'Connect Slack' button.","Implement a delete-and-recreate flow for reconfiguration scenarios.","Surface a clear UI message when a completed integration blocks a new setup."],"tags":["slack","oauth","integration","duplicate","configuration","csharp","aspnet"],"backgroundTag":null,"analyzedSha":"e93b962371d80964556f5590c6615f5160a437a1","analyzedAt":"2026-08-13T14:22:19.382Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}