bitwarden/server · warning · BadRequestException

There already exists a Slack integration for this organizati

Error message

There already exists a Slack integration for this organization

What it means

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.

Source

Thrown at src/Api/Dirt/Controllers/SlackIntegrationController.cs:58

        }

        var integrations = await integrationRepository.GetManyByOrganizationAsync(organizationId);
        var integration = integrations.FirstOrDefault(i => i.Type == IntegrationType.Slack);

        if (integration is null)
        {
            // No slack integration exists, create Initiated version
            integration = await integrationRepository.CreateAsync(new OrganizationIntegration
            {
                OrganizationId = organizationId,
                Type = IntegrationType.Slack,
                Configuration = null,
            });
        }
        else if (integration.Configuration is not null)
        {
            // A Completed (fully configured) Slack integration already exists, throw to prevent overriding
            throw new BadRequestException("There already exists a Slack integration for this organization");

        } // An Initiated slack integration exits, re-use it and kick off a new OAuth flow

        var state = IntegrationOAuthState.FromIntegration(integration, timeProvider);
        var redirectUrl = slackService.GetRedirectUrl(
            callbackUrl: callbackUrl,
            state: state.ToString()
        );

        if (string.IsNullOrEmpty(redirectUrl))
        {
            throw new NotFoundException();
        }

        return Redirect(redirectUrl);
    }

    [HttpGet("integrations/slack/create", Name = "SlackIntegration_Create")]

View on GitHub (pinned to e93b962371)

Solutions

  1. Delete the existing completed Slack integration for the organization before initiating a new OAuth flow.
  2. Provide a UI check that disables the 'Connect Slack' button when a completed integration already exists.
  3. If reconfiguration is legitimately needed, implement a delete-then-recreate workflow.

Example fix

// before
await api.InitiateSlackOAuthAsync(orgId); // throws if already configured

// after
var existing = await api.GetSlackIntegrationAsync(orgId);
if (existing?.Configuration != null)
{
    await api.DeleteSlackIntegrationAsync(orgId);
}
await api.InitiateSlackOAuthAsync(orgId);
Defensive patterns

Strategy: validation

Validate before calling

// Check for existing completed integration before initiating
var integrations = await integrationRepository.GetManyByOrganizationAsync(orgId);
var existing = integrations.FirstOrDefault(i => i.Type == IntegrationType.Slack);
if (existing?.Configuration != null)
    return Conflict("A completed Slack integration already exists. Delete it first to reconfigure.");
// safe to initiate

Type guard

public static bool HasCompletedSlackIntegration(IEnumerable<OrganizationIntegration> integrations) =>
    integrations.Any(i => i.Type == IntegrationType.Slack && i.Configuration != null);

Try / catch

try
{
    await _slackService.InitiateOAuthAsync(orgId);
}
catch (BadRequestException ex) when (ex.Message.Contains("already exists"))
{
    return Conflict(ex.Message);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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