{"record":{"id":"d24b1265ff13378f","repo":"RocketChat/Rocket.Chat","slug":"invalid-user-d24b12","errorCode":null,"errorMessage":"invalid-user","messagePattern":"invalid-user","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/lib/messages.ts","lineNumber":27,"sourceCode":"\troomId,\n\tpagination: { offset, count, sort },\n}: {\n\tuid: string;\n\troomId: string;\n\tpagination: { offset: number; count: number; sort: FindOptions<IMessage>['sort'] };\n}): Promise<{\n\tmessages: IMessage[];\n\tcount: number;\n\toffset: number;\n\ttotal: number;\n}> {\n\tconst room = await Rooms.findOneById(roomId);\n\tif (!room || !(await canAccessRoomAsync(room, { _id: uid }))) {\n\t\tthrow new Error('error-not-allowed');\n\t}\n\tconst user = await Users.findOneById<Pick<IUser, 'username'>>(uid, { projection: { username: 1 } });\n\tif (!user) {\n\t\tthrow new Error('invalid-user');\n\t}\n\n\tconst { cursor, totalCount } = Messages.findPaginatedVisibleByMentionAndRoomId(user.username, roomId, {\n\t\tsort: sort || { ts: -1 },\n\t\tskip: offset,\n\t\tlimit: count,\n\t});\n\n\tconst [messages, total] = await Promise.all([cursor.toArray(), totalCount]);\n\n\treturn {\n\t\tmessages,\n\t\tcount: messages.length,\n\t\toffset,\n\t\ttotal,\n\t};\n}\n","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/lib/messages.ts#L9-L45","documentation":"Inside findMentionedMessages (chat.getMentionedMessages flow), after room access passes, the helper loads the authenticated user by uid with a username projection to search for mentions of that username. If no user document exists for the uid on the request (Users.findOneById returns null) it throws plain Error 'invalid-user'. In practice this only happens when the auth token references a user that has since been deleted or the token is corrupt yet passed authentication.","triggerScenarios":"Calling chat.getMentionedMessages with a token for a user deleted between token issuance and this request, or a hand-crafted/expired session whose userId no longer resolves.","commonSituations":"Long-lived bot/personal access token kept after the account was removed; user deleted mid-session while a client retried; workspace data restored from a backup that lacks the user row.","solutions":["Re-authenticate: obtain a fresh token for a user that exists (check with GET /api/v1/me)","If the account was deleted, recreate it or switch the integration to a service account","For flaky occurrences, inspect whether a concurrent deletion is running"],"exampleFix":"// before\nGET /api/v1/chat.getMentionedMessages  (X-Auth-Token of deleted user) -> invalid-user\n\n// after\nPOST /api/v1/login { \"user\": \"live.bot\", \"password\": \"...\" }  // fresh token, then retry","handlingStrategy":"try-catch","validationCode":"async function assertTokenAlive(client) {\n  const me = await client.get('/api/v1/me');\n  if (me.status === 401) throw new Error('token stale — re-authenticate');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await client.get('/api/v1/chat.getMentionedMessages', { params: { roomId } });\n} catch (e: any) {\n  if ((e?.response?.data?.error ?? '') === 'invalid-user') {\n    // authed uid no longer exists: drop cached token, re-login once, then retry\n    await invalidateTokenAndReauth();\n  }\n  throw e;\n}","preventionTips":["Rotate long-lived tokens for service accounts rather than keeping them forever","Invalidate stored credentials whenever /api/v1/me returns 401","Avoid issuing tokens for users slated for deletion"],"tags":["rest-api","chat","auth","user-lookup"],"backgroundTag":"user-not-found","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}