{"record":{"id":"69dd081c1f5fddc4","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-69dd08","errorCode":"error-invalid-user","errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/rooms/addRoomLeader.ts","lineNumber":34,"sourceCode":"\tinterface ServerMethods {\n\t\taddRoomLeader(rid: IRoom['_id'], userId: IUser['_id']): boolean;\n\t}\n}\n\nexport const addRoomLeader = async (fromUserId: IUser['_id'], rid: IRoom['_id'], userId: IUser['_id']): Promise<boolean> => {\n\tcheck(rid, String);\n\tcheck(userId, String);\n\n\tif (!(await hasPermissionAsync(fromUserId, 'set-leader', rid))) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', {\n\t\t\tmethod: 'addRoomLeader',\n\t\t});\n\t}\n\n\tconst user = await Users.findOneById(userId);\n\n\tif (!user?.username) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\tmethod: 'addRoomLeader',\n\t\t});\n\t}\n\n\tconst subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, user._id);\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: 'addRoomLeader',\n\t\t});\n\t}\n\n\tif (subscription.roles && Array.isArray(subscription.roles) === true && subscription.roles.includes('leader') === true) {\n\t\tthrow new Meteor.Error('error-user-already-leader', 'User is already a leader', {\n\t\t\tmethod: 'addRoomLeader',\n\t\t});\n\t}\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/rooms/addRoomLeader.ts#L16-L52","documentation":"After the permission check, addRoomLeader loads the target user with Users.findOneById(userId); if the document is missing or has no username, it throws error-invalid-user. A Rocket.Chat user without a username cannot receive a room role because the subscription lookup and the 'subscription-role-added' system message both key off username.","triggerScenarios":"Passing a deleted or never-existing userId; targeting an app/bot or shadow user created without a username; the user was deleted between the member list rendering and the role-change call.","commonSituations":"Stale member lists in admin UIs; users removed mid-session; imported accounts with null usernames.","solutions":["Verify the target userId exists and has a username (e.g. GET /v1/users.info) before calling.","Refresh the member list so deleted users cannot be selected.","If usernames are missing on legitimate users, fix the user records first."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// confirm target user exists with a username before promoting\nconst res = await fetch(`/api/v1/users.info?userId=${userId}`, { headers }).then((r) => r.json());\nif (!res.success || !res.user?.username) {\n\tthrow new Error('Target user missing or has no username');\n}","typeGuard":"function isPromotableUser(u: { _id?: string; username?: string } | null | undefined): u is { _id: string; username: string } {\n\treturn !!u?._id && typeof u.username === 'string' && u.username.length > 0;\n}","tryCatchPattern":"try {\n\tawait Meteor.callAsync('addRoomLeader', rid, userId);\n} catch (e: any) {\n\tif (e?.error === 'error-invalid-user') {\n\t\t// target userId invalid: refresh the member list, pick again\n\t}\n}","preventionTips":["Refresh member lists so deleted users cannot be selected.","Reject userIds that are empty or not 17-char Mongo ids.","Skip app/bot accounts without usernames in role-management UIs."],"tags":["meteor-methods","users","not-found","rooms"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}