{"record":{"id":"b51c565914ca157c","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-user-b51c56","errorCode":"error-invalid-user","errorMessage":"error-invalid-user","messagePattern":"error-invalid-user","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/v1/omnichannel/room.ts","lineNumber":412,"sourceCode":");\n\ntype LivechatAnalyticsEndpoints = ExtractRoutesFromAPI<typeof livechatVisitorDepartmentTransfer>;\ndeclare module '@rocket.chat/rest-typings' {\n\t// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-empty-interface\n\tinterface Endpoints extends LivechatAnalyticsEndpoints {}\n}\n\nAPI.v1.addRoute(\n\t'livechat/room.join',\n\t{ authRequired: true, permissionsRequired: ['view-l-room'], validateParams: isLiveChatRoomJoinProps },\n\t{\n\t\tasync get() {\n\t\t\tconst { roomId } = this.queryParams;\n\n\t\t\tconst { user } = this;\n\n\t\t\tif (!user) {\n\t\t\t\tthrow new Error('error-invalid-user');\n\t\t\t}\n\n\t\t\tconst room = await LivechatRooms.findOneById(roomId);\n\n\t\t\tif (!room) {\n\t\t\t\tthrow new Error('error-invalid-room');\n\t\t\t}\n\n\t\t\tif (!room.open) {\n\t\t\t\tthrow new Error('room-closed');\n\t\t\t}\n\n\t\t\tif (!(await Omnichannel.isWithinMACLimit(room))) {\n\t\t\t\tthrow new Error('error-mac-limit-reached');\n\t\t\t}\n\n\t\t\tif (!(await canAccessRoomAsync(room, user))) {\n\t\t\t\tthrow new Error('error-not-allowed');","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/omnichannel/room.ts#L394-L430","documentation":"Thrown by GET livechat/room.join when this.user is null/undefined. The route declares authRequired: true, so the framework should populate this.user from the authenticated session; if it is still missing the authenticated principal could not be resolved to a user document. This is essentially an auth-resolution failure after the auth middleware ran.","triggerScenarios":"GET livechat/room.join?roomId=... with a token whose user was deleted between token issuance and the request, or with a malformed auth header that passed the middleware but resolved to no user object.","commonSituations":"User account deleted/deactivated while their session token was still valid; API client using a stale X-Auth-Token after the user was removed; a custom auth plugin that returns success without attaching a valid user; clock/token skew against the sessions collection.","solutions":["Re-authenticate to obtain a fresh token for an active user account.","Confirm the user account exists and is active (GET /api/v1/me) before calling room.join.","If using a service account, ensure it is not deleted and still holds the required roles/permissions.","Invalidate sessions for deleted users so the middleware rejects them before they reach the handler."],"exampleFix":"// before\nawait GET('/api/v1/livechat/room.join', { roomId }, { headers: { 'X-Auth-Token': staleToken } });\n\n// after\nconst me = await GET('/api/v1/me', { headers: { 'X-Auth-Token': token } });\nif (!me) reauthenticate();\nawait GET('/api/v1/livechat/room.join', { roomId }, { headers: { 'X-Auth-Token': freshToken } });","handlingStrategy":"validation","validationCode":"const me = await GET('/api/v1/me', { headers: authHeaders });\nif (!me || !me._id) { await reauthenticate(); return; }","typeGuard":"null","tryCatchPattern":"try {\n  await GET('/api/v1/livechat/room.join', { roomId });\n} catch (e) {\n  if (e.message === 'error-invalid-user') { clearSession(); redirectToLogin(); return; }\n  throw e;\n}","preventionTips":["Call /api/v1/me on app start to confirm the token resolves to a live user.","Invalidate sessions server-side when users are deleted/deactivated.","Avoid long-lived tokens for accounts that may be rotated out."],"tags":["omnichannel","livechat","auth","user-resolution","room-join"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}