{"record":{"id":"1ef9e61fff38e543","repo":"RocketChat/Rocket.Chat","slug":"room-with-id-transferdata-room-not-found","errorCode":null,"errorMessage":"Room with id ${transferData.room} not found","messagePattern":"Room with id (.+?) not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/app/apps/server/bridges/listeners.ts","lineNumber":443,"sourceCode":"\t\t\t\tconst [agentData] = args.payload;\n\t\t\t\treturn this.orch\n\t\t\t\t\t.getManager()\n\t\t\t\t\t.getListenerManager()\n\t\t\t\t\t.executeListener(args.event, {\n\t\t\t\t\t\troom: (await this.orch.getConverters().get('rooms').convertRoom(agentData.room)) as IAppsLivechatRoom,\n\t\t\t\t\t\tagent: this.orch.getConverters().get('users').convertToApp(agentData.user),\n\t\t\t\t\t});\n\n\t\t\tcase AppInterface.IPostLivechatRoomTransferred: {\n\t\t\t\tconst [transferData] = args.payload;\n\t\t\t\tconst converter = transferData.type === LivechatTransferEventType.AGENT ? 'users' : 'departments';\n\n\t\t\t\tconst room = await this.orch.getConverters().get('rooms').convertById(transferData.room);\n\t\t\t\tconst from = await this.orch.getConverters().get(converter).convertById(transferData.from);\n\t\t\t\tconst to = await this.orch.getConverters().get(converter).convertById(transferData.to);\n\n\t\t\t\tif (!room) {\n\t\t\t\t\tthrow new Error(`Room with id ${transferData.room} not found`);\n\t\t\t\t}\n\n\t\t\t\tif (!to) {\n\t\t\t\t\tthrow new Error(`Transfer to entity with id ${transferData.to} not found`);\n\t\t\t\t}\n\n\t\t\t\treturn this.orch\n\t\t\t\t\t.getManager()\n\t\t\t\t\t.getListenerManager()\n\t\t\t\t\t.executeListener(args.event, {\n\t\t\t\t\t\troom,\n\t\t\t\t\t\tfrom: from as NonNullable<typeof from>, // type definition in the apps-engine seems to be incorrect\n\t\t\t\t\t\tto,\n\t\t\t\t\t\ttype: transferData.type,\n\t\t\t\t\t});\n\t\t\t}\n\n\t\t\tcase AppInterface.IPostLivechatGuestSaved: {","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/app/apps/server/bridges/listeners.ts#L425-L461","documentation":"UserDataFiles (GDPR export downloads) resolves the requester via FileUpload.getRequestUserId — rc_uid/rc_token from the query or cookies, or x-user-id/x-auth-token headers — and only permits the export's owner (uid === file.userId). Missing credentials, an invalid/expired token, or any other user yields a bodyless 403. This is stricter than room-based upload protection: exports are owner-only, always.","triggerScenarios":"Downloading another user's export link while authenticated as someone else (including admins); anonymous fetch of an export URL; rc_token expired between the export email and the click; automated fetchers that strip cookies/headers.","commonSituations":"Forwarded export links; curl/wget downloads without credentials; admins attempting to fetch users' exports directly instead of through the proper flow; sessions expiring before download.","solutions":["Download the export while logged in as the user who requested it, using the link from their notification/email","Pass x-user-id and x-auth-token headers (or rc_uid/rc_token query params) of the owner on programmatic requests","If the token expired, log in again and reopen the export link","Do not try to bypass with admin privileges — the check is owner identity, not permission"],"exampleFix":"// before\nawait fetch(`${site}/file-upload/${fileId}/${name}`);\n// after: authenticate as the owner\nawait fetch(`${site}/file-upload/${fileId}/${name}`, { headers: { 'x-user-id': uid, 'x-auth-token': token } });","handlingStrategy":"validation","validationCode":"const uid = await FileUpload.getRequestUserId(req);\nif (!uid || uid !== file.userId) { /* do not fetch; have the owner's session make the request */ }","typeGuard":"const isOwnerRequest = (requesterId?: string, ownerId: string): boolean => requesterId === ownerId;","tryCatchPattern":"On 403 from a user-data export link, redirect to login and retry once as the owner; a second 403 means the authenticated user is not the owner — surface that explicitly.","preventionTips":["Send x-user-id/x-auth-token (or rc_uid/rc_token) on every export download","Never forward export links between users — ownership is enforced strictly","Expire export links server-side when tokens would outlive sessions"],"tags":["file-upload","http-403","gdpr","user-data-export","authorization"],"backgroundTag":"file-access-forbidden","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}