RocketChat/Rocket.Chat · error · Error
room-name-already-exists
Error message
room-name-already-exists
What it means
After the name-availability check, TeamService.create() also runs Rooms.findOneByName(team.name); if a room with that name already exists under a different id than the provided room.id, it throws room-name-already-exists — the team's channel would collide with an existing room name.
Source
Thrown at apps/meteor/server/services/team/service.ts:49
import { addUserToRoom } from '../../lib/rooms/addUserToRoom';
import { getSubscribedRoomsForUserWithDetails } from '../../lib/rooms/getRoomsWithSingleOwner';
import { removeUserFromRoom } from '../../lib/rooms/removeUserFromRoom';
import { saveRoomName } from '../../lib/rooms/settings';
import { saveRoomType } from '../../lib/rooms/settings/saveRoomType';
import { checkUsernameAvailability } from '../../lib/users/checkUsernameAvailability';
import { settings } from '../../settings';
export class TeamService extends ServiceClassInternal implements ITeamService {
protected name = 'team';
async create(uid: string, { team, room = { name: team.name, extraData: {} }, members, owner }: ITeamCreateParams): Promise<ITeam> {
if (!(await checkUsernameAvailability(team.name, 'room'))) {
throw new Error('team-name-already-exists');
}
const existingRoom = await Rooms.findOneByName(team.name, { projection: { _id: 1 } });
if (existingRoom && existingRoom._id !== room.id) {
throw new Error('room-name-already-exists');
}
const createdBy = await Users.findOneById<Pick<IUser, 'username' | '_id'>>(uid, {
projection: { username: 1 },
});
if (!createdBy) {
throw new Error('invalid-user');
}
// TODO add validations to `data` and `members`
const membersResult =
!members || !Array.isArray(members) || members.length === 0
? []
: await Users.findActiveByIdsOrUsernames(members, {
projection: { username: 1 },
}).toArray();
const memberUsernames = membersResult.map(({ username }) => username);View on GitHub (pinned to b2c16d5842)
Solutions
- Rename the team, or delete/rename the colliding room first
- If the existing room is intended to back the team, pass its id as room.id in the create params
- Pre-check Rooms.findOneByName(team.name) before submitting
Defensive patterns
Strategy: validation
Validate before calling
const existingRoom = await Rooms.findOneByName(team.name, { projections: { _id: 1 } });
if (existingRoom && existingRoom._id !== intendedRoomId) {
// a room already uses this name: pick another team name or pass this room.id deliberately
return markRoomNameTaken(team.name);
} Type guard
const isRoomNameFreeForTeam = async (name: string, roomId?: string): Promise<boolean> => {
const existing = await Rooms.findOneByName(name, { projections: { _id: 1 } });
return !existing || existing._id === roomId;
}; Try / catch
try {
await teamService.create(uid, params);
} catch (err) {
if (err instanceof Error && err.message === 'room-name-already-exists') {
// rename the team or delete/rename the colliding room; retrying the same name always fails
return suggestAlternativeNames(params.team.name);
}
throw err;
} Prevention
- Check Rooms.findOneByName before creating teams whose channel names collide
- If reusing an existing room as the team channel, pass its exact room.id
- Remove orphaned channels left by failed team creates before retrying
When it happens
Trigger: Creating a team when a channel/private room with the same name already exists (and the caller did not pass that exact room.id); races where two creates pick the same name at once.
Common situations: A pre-existing channel shares the desired team name; a deleted team left its channel behind; users re-running a failed create whose channel was actually created.
Related errors
- team-name-already-exists
- room-not-on-team
- invalid-list-of-rooms
- Param ${params.teams.key} must be an array
- error-cannot-delete-team-channel
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/6de9b9b3bcc413f6.
Report an issue: GitHub.