{"record":{"id":"d840fb14d02b3541","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-d840fb","errorCode":"error-invalid-user","errorMessage":"Invalid user","messagePattern":"Invalid user","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/messaging/reactions/setReaction.ts","lineNumber":114,"sourceCode":"export async function executeSetReaction(\n\tuserId: string,\n\treaction: string,\n\tmessageParam: IMessage['_id'] | IMessage,\n\tshouldReact?: boolean,\n) {\n\t// Check if the emoji is valid before proceeding\n\tconst reactionWithoutColons = reaction.replace(/:/g, '');\n\treaction = `:${reactionWithoutColons}:`;\n\n\tif (!emoji.list[reaction] && (await EmojiCustom.countByNameOrAlias(reactionWithoutColons)) === 0) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'Invalid emoji provided.', {\n\t\t\tmethod: 'setReaction',\n\t\t});\n\t}\n\n\tconst user = await Users.findOneById(userId);\n\tif (!user) {\n\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'setReaction' });\n\t}\n\n\tconst message = typeof messageParam === 'string' ? await Messages.findOneById(messageParam) : messageParam;\n\tif (!message) {\n\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'setReaction' });\n\t}\n\n\tconst userAlreadyReacted = Boolean(message.reactions?.[reaction]?.usernames?.includes(user.username as string));\n\n\t// When shouldReact was not informed, toggle the reaction.\n\tif (shouldReact === undefined) {\n\t\tshouldReact = !userAlreadyReacted;\n\t}\n\n\tif (userAlreadyReacted === shouldReact) {\n\t\treturn;\n\t}\n","sourceCodeStart":96,"sourceCodeEnd":132,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/messaging/reactions/setReaction.ts#L96-L132","documentation":"After the emoji check passes, executeSetReaction loads the acting user with Users.findOneById(userId) and throws Meteor.Error('error-invalid-user', 'Invalid user') when no user document matches. The method invocation carried a userId that does not resolve to a persisted account: deleted user, corrupted id, or an unauthenticated caller.","triggerScenarios":"A 'setReaction' DDP invocation whose bound this.userId points to a deleted or nonexistent user (account removed while the socket stayed open); server code calling executeSetReaction('bad-id', ...); tests invoking it with fabricated ids that were never inserted.","commonSituations":"Account deleted/deactivated mid-session with the DDP connection reused; database migrations leaving dangling user ids; unit tests using mock ids without seeding the Users collection.","solutions":["Client: treat it as an invalid session - log out and re-authenticate so this.userId refreshes","Server code: verify Users.findOneById(userId) exists before delegating to executeSetReaction","In tests, insert the user document (or stub the model) before invoking the reaction flow"],"exampleFix":"// before (test/helper invoking the internal API)\nawait executeSetReaction('missing-user-id', 'tada', messageId); // throws error-invalid-user\n\n// after\nconst user = await Users.findOneById(userId, { projections: { _id: 1 } });\nif (!user) throw new Meteor.Error('error-invalid-user', 'Invalid user');\nawait executeSetReaction(user._id, 'tada', messageId);","handlingStrategy":"try-catch","validationCode":"// Server-side wrapper: confirm the user exists before delegating\nconst user = await Users.findOneById(userId, { projections: { _id: 1 } });\nif (!user) {\n  return handleInvalidSession(userId);\n}\nawait executeSetReaction(userId, reaction, messageId);","typeGuard":"const isExistingUserId = async (id: string): Promise<boolean> =>\n  Boolean(await Users.findOneById(id, { projections: { _id: 1 } }));","tryCatchPattern":"Meteor.call('setReaction', 'tada', messageId, (err) => {\n  if (err?.error === 'error-invalid-user') {\n    Meteor.logout(); // local session points at a deleted account - force re-auth\n  }\n});","preventionTips":["Treat error-invalid-user from methods as session-invalidating, not retryable","Auto-logout clients when the server reports their account missing","Do not cache user ids long-term in integrations; resolve them per operation"],"tags":["reactions","user-not-found","ddp-method"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}