{"record":{"id":"77783f5195225341","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-77783f","errorCode":"error-invalid-user","errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/users/saveUser/saveUser.ts","lineNumber":68,"sourceCode":"\tjoinDefaultChannels?: boolean;\n\tsendWelcomeEmail?: boolean;\n\n\tcustomFields?: Record<string, any>;\n\tactive?: boolean;\n\n\tfreeSwitchExtension?: string;\n};\nexport type UpdateUserData = RequiredField<SaveUserData, '_id'>;\nexport const isUpdateUserData = (params: SaveUserData): params is UpdateUserData => '_id' in params && !!params._id;\n\ntype SaveUserOptions = {\n\tauditStore?: UserChangedAuditStore;\n};\n\nconst findUserById = async (uid: IUser['_id']): Promise<IUser> => {\n\tconst user = await Users.findOneById(uid);\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user');\n\t}\n\n\treturn user;\n};\n\nconst _saveUser = (session?: ClientSession) =>\n\tasync function (userId: IUser['_id'], userData: SaveUserData, options?: SaveUserOptions) {\n\t\tconst performedBy = await findUserById(userId);\n\n\t\tconst oldUserData = userData._id && (await Users.findOneById(userData._id));\n\t\tif (oldUserData && isUserFederated(oldUserData)) {\n\t\t\tthrow new Meteor.Error('Edit_Federated_User_Not_Allowed', 'Not possible to edit a federated user');\n\t\t}\n\n\t\tawait validateUserData(userId, userData);\n\n\t\tawait callbacks.run('beforeSaveUser', {\n\t\t\tuser: userData,","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/users/saveUser/saveUser.ts#L50-L86","documentation":"saveUser's internal findUserById throws error-invalid-user when the acting user (the id passed as the first argument, used as 'performedBy' for audit) does not exist. This fires before any validation of the payload: the caller of saveUser must be a real user record.","triggerScenarios":"Calling saveUser(userId, userData) with a stale, deleted, or fabricated actor id; server code invoking saveUser with a request context whose user was removed between authentication and the save.","commonSituations":"Automation passing a hard-coded admin id that differs per environment; the acting admin's account deleted mid-session; tests without seeded users.","solutions":["Confirm the acting userId exists (Users.findOneById) before calling saveUser","In request-driven code, take the actor from the authenticated session instead of a parameter","In tests, seed the acting user first"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const actor = await Users.findOneById(actorId, { projections: { _id: 1 } });\nif (!actor) throw new Error('Acting user does not exist');\nawait saveUser(actorId, userData);","typeGuard":null,"tryCatchPattern":"try {\n  await saveUser(actorId, userData);\n} catch (e) {\n  if (isMeteorErrorCode(e, 'error-invalid-user')) {\n  \t// actor id is wrong/stale: re-resolve from the authenticated session\n  }\n}","preventionTips":["Derive the acting user from the authenticated request, never from a free parameter","Keep environment-specific admin ids in config, not hard-coded"],"tags":["users","save-user","lookup","audit"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}