RocketChat/Rocket.Chat · warning · Meteor.Error
error-user-already-in-room
error-user-already-in-room
Error message
You are already in the channel
What it means
Thrown by the /join slash command when the invoking user already has a subscription record for the target room. The handler first resolves the room and warns via ephemeral message if it is not visible, then checks Subscriptions.findOneByRoomIdAndUserId; any existing subscription document triggers this Meteor.Error with code 'error-user-already-in-room'. It prevents a duplicate join through Room.join().
Source
Thrown at apps/meteor/server/slashcommands/join/server.ts:40
channel = channel.replace('#', '');
const room = await Rooms.findOneByNameAndType(channel, 'c');
if (!room) {
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
msg: i18n.t('Channel_doesnt_exist', {
channelName: channel,
lng: settings.get('Language') || 'en',
}),
});
return;
}
const subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, userId, {
projection: { _id: 1 },
});
if (subscription) {
throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', {
method: 'slashCommands',
});
}
const user = await Users.findOneById(userId);
if (!user) {
throw new Meteor.Error('error-invalid-user', 'Invalid user', {
method: 'slashCommands',
});
}
await Room.join({ room, user });
},
options: {
description: 'Join_the_given_channel',
params: '#channel',
permission: 'view-c-room',
},
});View on GitHub (pinned to b2c16d5842)
Solutions
- Have the client check the user's subscription list (or room subscription cache) before invoking /join.
- On the server, catch the error and degrade to an informational message instead of surfacing a raw error toast.
- If an idempotent join is desired, replace the throw with an ephemeral 'already in channel' notice mirroring the room-not-found branch.
Example fix
// before
if (subscription) {
throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', { method: 'slashCommands' });
}
// after (idempotent join)
if (subscription) {
void api.broadcast('notify.ephemeralMessage', userId, message.rid, {
msg: i18n.t('You_are_already_in_the_channel', { lng: settings.get('Language') || 'en' }),
});
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Before running /join, check an existing subscription client-side
const subscribed = useUserSubscribed(roomId); // or Meteor.call('rooms/get', ...) check
if (!subscribed) {
await Meteor.callAsync('slashCommand', { command: 'join', params: `#${channelName}`, rid: currentRid });
} Try / catch
try { await Meteor.callAsync('slashCommand', {...}); } catch (e) { if (isMeteorError(e, 'error-user-already-in-room')) { /* informational: already a member */ return; } throw e; } Prevention
- Check the user's room subscription before exposing join actions.
- Use the returned ephemeral warnings path instead of re-issuing /join.
- In bots, treat already-in-room as success for idempotent join flows.
When it happens
Trigger: User types '/join #channel' (or clicks a join flow that calls the command) while already a member of that channel; the subscription lookup returns a document (only _id projected) and the error is thrown before Room.join runs.
Common situations: Stale client UI showing a join button for a channel the user already joined from another session/device; race where a user joins via invite and then runs /join; automated scripts or bots calling the join command idempotently.
Related errors
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/f708ec0c4639595d.
Report an issue: GitHub.