{"record":{"id":"934d6679a422d588","repo":"RocketChat/Rocket.Chat","slug":"error-duplicate-handle","errorCode":"error-duplicate-handle","errorMessage":"A room, team or user with name '${slugifiedRoomName}' already exists","messagePattern":"A room, team or user with name '(.+?)' already exists","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/rooms/settings/saveRoomName.ts","lineNumber":27,"sourceCode":"import { notifyOnIntegrationChangedByChannels, notifyOnSubscriptionChangedByRoomId } from '../../notifyListener';\nimport { checkUsernameAvailability } from '../../users/checkUsernameAvailability';\nimport { getValidRoomName } from '../../utils/lib/getValidRoomName';\nimport { roomCoordinator } from '../roomCoordinator';\n\nconst updateFName = async (rid: string, displayName: string): Promise<(UpdateResult | Document)[]> => {\n\tconst responses = await Promise.all([Rooms.setFnameById(rid, displayName), Subscriptions.updateFnameByRoomId(rid, displayName)]);\n\n\tif (responses[1]?.modifiedCount) {\n\t\tvoid notifyOnSubscriptionChangedByRoomId(rid);\n\t}\n\n\treturn responses;\n};\n\nconst updateRoomName = async (rid: string, displayName: string, slugifiedRoomName: string) => {\n\t// Check if the name is available\n\tif (!(await checkUsernameAvailability(slugifiedRoomName, 'room'))) {\n\t\tthrow new Meteor.Error('error-duplicate-handle', `A room, team or user with name '${slugifiedRoomName}' already exists`, {\n\t\t\tfunction: 'RocketChat.updateRoomName',\n\t\t\thandle: slugifiedRoomName,\n\t\t});\n\t}\n\n\tconst responses = await Promise.all([\n\t\tRooms.setNameById(rid, slugifiedRoomName, displayName),\n\t\tSubscriptions.updateNameAndAlertByRoomId(rid, slugifiedRoomName, displayName),\n\t]);\n\n\tif (responses[1]?.modifiedCount) {\n\t\tvoid notifyOnSubscriptionChangedByRoomId(rid);\n\t}\n\n\treturn responses;\n};\n\nexport async function saveRoomName(","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/rooms/settings/saveRoomName.ts#L9-L45","documentation":"Thrown by updateRoomName inside saveRoomName when checkUsernameAvailability(slugifiedRoomName, 'room') returns false (saveRoomName.ts:27) — the slugified target name collides with an existing room, team, or user handle, since these share one namespace. slugifiedRoomName comes from getValidRoomName(displayName, rid); the error embeds the offending handle in details { handle }. Code 'error-duplicate-handle'.","triggerScenarios":"Renaming a channel to a name already used by a user/room/team (e.g. 'general', an existing username); two admins renaming to the same free name simultaneously (check-then-set race between checkUsernameAvailability and Rooms.setNameById); a discussion/federation-unrelated path where slugified name equals a reserved handle.","commonSituations":"Renaming channels into well-known names ('support', 'admin') that exist as usernames; teams and channels competing for the same handle after a reorganization; bulk rename scripts not accounting for the shared namespace.","solutions":["Pick a different display name — the message names the exact conflicting handle","Rename or delete the conflicting user/room/team that owns the handle, if that object is the disposable one","Pre-check availability before offering the rename: await checkUsernameAvailability(slugified, 'room')","For programmatic renames, retry with a suffixed name (name-2) since a concurrent creator may have claimed the handle"],"exampleFix":"// before\nawait saveRoomName(rid, 'support', user);\n\n// after\nconst slug = await getValidRoomName('support', rid);\nif (!(await checkUsernameAvailability(slug, 'room'))) {\n\tthrow new Meteor.Error('error-duplicate-handle', `A room, team or user with name '${slug}' already exists`);\n}\nawait saveRoomName(rid, 'support', user);","handlingStrategy":"validation","validationCode":"const slugified = await getValidRoomName(displayName, rid);\nif (!(await checkUsernameAvailability(slugified, 'room'))) {\n\tthrow new Meteor.Error('error-duplicate-handle', `Name '${slugified}' is taken by a room, team or user`);\n}\nawait saveRoomName(rid, displayName, user);","typeGuard":null,"tryCatchPattern":"try {\n\tawait saveRoomName(rid, displayName, user);\n} catch (e) {\n\tif (e instanceof Meteor.Error && e.error === 'error-duplicate-handle') {\n\t\t// e.details.handle names the conflict; prompt for another name or auto-suffix\n\t}\n}","preventionTips":["Remember users, rooms and teams share one handle namespace — check all three before offering a name","For programmatic renames, fall back to name-2, name-3 on this error","Check availability right before the rename, not when the form loads, to shrink the race window"],"tags":["room","rename","duplicate","slug","namespace"],"backgroundTag":"duplicate-name","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}