{"record":{"id":"6dfed257dc03b4aa","repo":"RocketChat/Rocket.Chat","slug":"not-authorized","errorCode":"not-authorized","errorMessage":"Not authorized","messagePattern":"Not authorized","errorType":"error_code","errorClass":"NotAuthorizedError","httpStatus":null,"severity":"error","filePath":"apps/meteor/client/views/room/hooks/useOpenRoom.ts","lineNumber":70,"sourceCode":"\t\treturn { rid: sub.rid };\n\t}, [reference, type, user?._id]);\n\n\tconst result = useQuery({\n\t\t// we need to add uid and username here because `user` is not loaded all at once (see UserProvider -> Meteor.user())\n\t\tqueryKey: roomsQueryKeys.roomReference(reference, type, user?._id, user?.username),\n\n\t\t// Render immediately from local cache when we already know the rid; queryFn still runs in\n\t\t// the background to revalidate permissions / fetch fresh room fields.\n\t\tplaceholderData: tryCacheShortcut,\n\n\t\tqueryFn: async (): Promise<{ rid: IRoom['_id'] }> => {\n\t\t\tconst cached = tryCacheShortcut();\n\t\t\tif (cached) {\n\t\t\t\tLegacyRoomManager.open({ typeName: type + reference, rid: cached.rid });\n\t\t\t\treturn cached;\n\t\t\t}\n\t\t\tif ((user && !user.username) || (!user && !allowAnonymousRead)) {\n\t\t\t\tthrow new NotAuthorizedError();\n\t\t\t}\n\n\t\t\tif (!reference || !type) {\n\t\t\t\tthrow new RoomNotFoundError(undefined, { type, reference });\n\t\t\t}\n\n\t\t\tlet roomData: IRoom;\n\t\t\ttry {\n\t\t\t\troomData = await getRoomByTypeAndName(type, reference);\n\t\t\t} catch (error) {\n\t\t\t\tconst errorCode = error && typeof error === 'object' && 'error' in error ? error.error : undefined;\n\n\t\t\t\t// \"No permission\" means the room exists but the user can't see it — surface the\n\t\t\t\t// not-found/no-access screen rather than retrying it as a transient failure.\n\t\t\t\tif (errorCode === 'error-no-permission') {\n\t\t\t\t\tthrow new RoomNotFoundError(undefined, { type, reference });\n\t\t\t\t}\n","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/2f18297792c973da326be7253f497d239ea6f2b0/apps/meteor/client/views/room/hooks/useOpenRoom.ts#L52-L88","documentation":"NotAuthorizedError (error id `not-authorized`) thrown inside the useOpenRoom react-query queryFn before any server call. It fires when the current user is logged in but has no username, or when there is no logged-in user and anonymous read is disabled for the workspace. It signals that the caller is not permitted to resolve/open a room by name at all.","triggerScenarios":"Opening a room route while logged in as an account whose username is not yet set (e.g. user creation flow incomplete), or an anonymous visitor hitting /channel/:name when the Accounts_SetAnonymousRead setting is false (EE).","commonSituations":"Anonymous read toggle turned off after links were shared publicly; a half-provisioned bot/ghost account without a username; tests that render room routes without a fully seeded user.","solutions":["If you are the visitor: log in with a valid account that has a username.","If anonymous access is intended, enable Accounts_SetAnonymousRead (Enterprise Edition) in workspace settings.","If the account lacks a username, complete the user profile/username via the user settings or admin UI, then reload the room route.","In app code, gate room routes on a logged-in-with-username check and redirect to home/login instead of letting useOpenRoom throw."],"exampleFix":"// before\nconst { data } = useOpenRoom(type, reference); // throws not-authorized for anonymous\n\n// after\nconst user = useUserId();\nconst username = useUserDisplayName(); // resolves only when username set\nif (!user && !anonymousReadEnabled) {\n\treturn <NotAuthorizedPage />;\n}\nconst { data } = useOpenRoom(type, reference);","handlingStrategy":"validation","validationCode":"const canOpenRoom = (user: { username?: string } | null, allowAnonymousRead: boolean): boolean =>\n\tBoolean(user?.username) || (!user && allowAnonymousRead);","typeGuard":"const isNotAuthorizedError = (error: unknown): error is RocketChatError<'not-authorized'> =>\n\tBoolean(error && typeof error === 'object' && 'error' in error && (error as { error: string }).error === 'not-authorized');","tryCatchPattern":"try {\n\tconst { rid } = await openRoomQueryFn();\n} catch (error) {\n\tif (isNotAuthorizedError(error)) {\n\t\tredirect('/home'); // not retriable: fix auth state instead\n\t\treturn;\n\t}\n\tthrow error;\n}","preventionTips":["Gate room routes on an authenticated-with-username check before mounting the room view.","If anonymous browsing is required, verify the Accounts_SetAnonymousRead EE setting is on.","Complete username setup during account provisioning so no user lingers without one."],"tags":["client","authorization","anonymous-access","react-query"],"backgroundTag":"permission-denied","analyzedSha":"2f18297792c973da326be7253f497d239ea6f2b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}