Skip to content

Commit b77dd69

Browse files
fix(slack): 409 on custom-bot name collision instead of silently returning the existing credential
The service-account dedupe matches on displayName, which defaults to the Slack team name — shared by every bot in that workspace. A second unnamed bot create returned the first credential as success, orphaning the new id already pasted into the Slack Request URL. Same-id replays stay idempotent; different-id collisions now fail loudly so the wizard prompts for a distinct name.
1 parent 9146a33 commit b77dd69

1 file changed

Lines changed: 19 additions & 0 deletions

File tree

apps/sim/app/api/credentials/route.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,25 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
417417
})
418418

419419
if (existingCredential) {
420+
// A retried custom-bot create with the SAME pre-generated id is an
421+
// idempotent replay and falls through to the normal existing-credential
422+
// path. Any other name collision must fail loudly: returning the existing
423+
// row as success would orphan the new id already embedded in the user's
424+
// Slack Request URL (Slack would post to a URL no credential resolves).
425+
if (
426+
resolvedProviderId === SLACK_CUSTOM_BOT_PROVIDER_ID &&
427+
clientCredentialId &&
428+
existingCredential.id !== clientCredentialId
429+
) {
430+
return NextResponse.json(
431+
{
432+
code: 'duplicate_display_name',
433+
error: `A Slack bot named "${resolvedDisplayName}" already exists in this workspace. Give this bot a different name.`,
434+
},
435+
{ status: 409 }
436+
)
437+
}
438+
420439
const access = await getCredentialActorContext(existingCredential.id, session.user.id, {
421440
workspaceAccess,
422441
})

0 commit comments

Comments
 (0)