{"record":{"id":"c59e6e95391e8534","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-c59e6e","errorCode":"error-invalid-user","errorMessage":"Invalid user to unmute","messagePattern":"Invalid user to unmute","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/unmuteUserInRoom.ts","lineNumber":53,"sourceCode":"\t\tthrow new Meteor.Error('error-invalid-room-type', `${room.t} is not a valid room type`, {\n\t\t\tmethod: 'unmuteUserInRoom',\n\t\t\ttype: room.t,\n\t\t});\n\t}\n\n\tconst subscription = await Subscriptions.findOneByRoomIdAndUsername(data.rid, data.username, {\n\t\tprojection: { _id: 1 },\n\t});\n\n\tif (!subscription) {\n\t\tthrow new Meteor.Error('error-user-not-in-room', 'User is not in this room', {\n\t\t\tmethod: 'unmuteUserInRoom',\n\t\t});\n\t}\n\n\tconst unmutedUser = await Users.findOneByUsernameIgnoringCase(data.username);\n\tif (!unmutedUser?.username) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user to unmute', {\n\t\t\tmethod: 'unmuteUserInRoom',\n\t\t});\n\t}\n\n\tconst fromUser = await Users.findOneById(fromId);\n\tif (!fromUser) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\tmethod: 'unmuteUserInRoom',\n\t\t});\n\t}\n\n\tawait callbacks.run('beforeUnmuteUser', { unmutedUser, fromUser }, room);\n\n\tif (room.ro) {\n\t\tawait Rooms.unmuteReadOnlyUsernameByRoomId(data.rid, unmutedUser.username);\n\t} else {\n\t\tawait Rooms.unmuteMutedUsernameByRoomId(data.rid, unmutedUser.username);\n\t}","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/unmuteUserInRoom.ts#L35-L71","documentation":"Thrown by `unmuteUserInRoom` when the subscription lookup succeeded but `Users.findOneByUsernameIgnoringCase(data.username)` returned no user (or a user document without a username). It means the room membership record exists while the corresponding user record does not — a data inconsistency such as a deleted user whose subscription lingered, or a username with no matching user document at all.","triggerScenarios":"Calling `unmuteUserInRoom` with a username whose subscription exists but whose user was deleted (user removed while muted, leaving an orphan subscription), or with a username that happens to match a subscription but has no user record (e.g. after a rename the old subscription key was kept).","commonSituations":"Partial user deletion that left subscriptions behind; workspaces imported or restored inconsistently; test fixtures that create subscriptions without matching users; automated scripts unmuting by username against stale data.","solutions":["Confirm the user exists first, e.g. `GET /api/v1/users.info?username=<username>`, before calling the method.","If the user was deleted, remove the orphan subscription from the room instead of unmuting (membership cleanup).","Resolve the username from the subscription record (`sub.u.username`) so renames/casing cannot diverge.","Audit for orphan subscriptions (`Subscriptions` entries whose `u._id` has no `users` document) and clean them up."],"exampleFix":"// before\nMeteor.call('unmuteUserInRoom', { rid, username });\n\n// after - confirm the user document exists first (REST)\nconst res = await fetch(`/api/v1/users.info?username=${encodeURIComponent(username)}`, {\n  headers: { 'X-Auth-Token': token, 'X-User-Id': uid },\n});\nif (!res.ok) {\n  // user record gone: clean up the orphan subscription instead of unmuting\n  return;\n}\nMeteor.call('unmuteUserInRoom', { rid, username });","handlingStrategy":"validation","validationCode":"// verify both membership AND user existence before unmuting\nconst sub = await Subscriptions.findOneByRoomIdAndUsername(rid, username);\nconst user = sub && await Users.findOneByUsernameIgnoringCase(username);\nif (sub && user?.username) {\n  await Meteor.callAsync('unmuteUserInRoom', { rid, username: user.username });\n}","typeGuard":"const hasUserRecord = async (username: string): Promise<boolean> =>\n  Boolean(await Users.findOneByUsernameIgnoringCase(username));","tryCatchPattern":"try {\n  await Meteor.callAsync('unmuteUserInRoom', { rid, username });\n} catch (e: any) {\n  if (e?.error === 'error-invalid-user' && e?.reason === 'Invalid user to unmute') {\n    // user document missing: clean up the orphan subscription instead of retrying\n  }\n}","preventionTips":["Delete users through the supported flows so their subscriptions are cleaned up atomically.","Periodically audit for subscriptions whose u._id has no users document.","Avoid creating test fixtures with subscriptions but no users."],"tags":["meteor","rooms","users","data-consistency"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}