{"record":{"id":"f708ec0c4639595d","repo":"RocketChat/Rocket.Chat","slug":"error-user-already-in-room","errorCode":"error-user-already-in-room","errorMessage":"You are already in the channel","messagePattern":"You are already in the channel","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"warning","filePath":"apps/meteor/server/slashcommands/join/server.ts","lineNumber":40,"sourceCode":"\t\tchannel = channel.replace('#', '');\n\n\t\tconst room = await Rooms.findOneByNameAndType(channel, 'c');\n\t\tif (!room) {\n\t\t\tvoid api.broadcast('notify.ephemeralMessage', userId, message.rid, {\n\t\t\t\tmsg: i18n.t('Channel_doesnt_exist', {\n\t\t\t\t\tchannelName: channel,\n\t\t\t\t\tlng: settings.get('Language') || 'en',\n\t\t\t\t}),\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(room._id, userId, {\n\t\t\tprojection: { _id: 1 },\n\t\t});\n\n\t\tif (subscription) {\n\t\t\tthrow new Meteor.Error('error-user-already-in-room', 'You are already in the channel', {\n\t\t\t\tmethod: 'slashCommands',\n\t\t\t});\n\t\t}\n\n\t\tconst user = await Users.findOneById(userId);\n\t\tif (!user) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\tmethod: 'slashCommands',\n\t\t\t});\n\t\t}\n\t\tawait Room.join({ room, user });\n\t},\n\toptions: {\n\t\tdescription: 'Join_the_given_channel',\n\t\tparams: '#channel',\n\t\tpermission: 'view-c-room',\n\t},\n});","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/slashcommands/join/server.ts#L22-L58","documentation":"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().","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nif (subscription) {\n  throw new Meteor.Error('error-user-already-in-room', 'You are already in the channel', { method: 'slashCommands' });\n}\n\n// after (idempotent join)\nif (subscription) {\n  void api.broadcast('notify.ephemeralMessage', userId, message.rid, {\n    msg: i18n.t('You_are_already_in_the_channel', { lng: settings.get('Language') || 'en' }),\n  });\n  return;\n}","handlingStrategy":"validation","validationCode":"// Before running /join, check an existing subscription client-side\nconst subscribed = useUserSubscribed(roomId); // or Meteor.call('rooms/get', ...) check\nif (!subscribed) {\n  await Meteor.callAsync('slashCommand', { command: 'join', params: `#${channelName}`, rid: currentRid });\n}","typeGuard":null,"tryCatchPattern":"try { await Meteor.callAsync('slashCommand', {...}); } catch (e) { if (isMeteorError(e, 'error-user-already-in-room')) { /* informational: already a member */ return; } throw e; }","preventionTips":["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."],"tags":["rocket-chat","slash-command","room-membership","meteor"],"backgroundTag":"duplicate-resource-creation","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}