{"record":{"id":"0b7b341b3a93571f","repo":"RocketChat/Rocket.Chat","slug":"error-not-allowed-0b7b34","errorCode":"error-not-allowed","errorMessage":"Not allowed","messagePattern":"Not allowed","errorType":"exception","errorClass":"Meteor.Error","httpStatus":403,"severity":"error","filePath":"apps/meteor/server/api/v1/im.ts","lineNumber":178,"sourceCode":"\t\t\t\t\ttype: 'boolean',\n\t\t\t\t\tenum: [true],\n\t\t\t\t},\n\t\t\t},\n\t\t\trequired: ['success'],\n\t\t\tadditionalProperties: false,\n\t\t}),\n\t},\n};\n\nconst dmDeleteAction = <Path extends string>(_path: Path): TypedAction<typeof dmDeleteEndpointsProps, Path> =>\n\tasync function action() {\n\t\tconst { room } = await findDirectMessageRoom(this.bodyParams, this.userId);\n\n\t\tconst canAccess =\n\t\t\t(await canAccessRoomIdAsync(room._id, this.userId)) || (await hasPermissionAsync(this.user, 'view-room-administration'));\n\n\t\tif (!canAccess) {\n\t\t\tthrow new Meteor.Error('error-not-allowed', 'Not allowed');\n\t\t}\n\n\t\tawait eraseRoom(room._id, this.user);\n\n\t\treturn API.v1.success();\n\t};\n\nconst dmCloseAction = <Path extends string>(_path: Path): TypedAction<typeof dmCloseEndpointsProps, Path> =>\n\tasync function action() {\n\t\tconst { roomId } = this.bodyParams;\n\t\tif (!roomId) {\n\t\t\tthrow new Meteor.Error('error-room-param-not-provided', 'Body param \"roomId\" is required');\n\t\t}\n\t\tif (!this.userId) {\n\t\t\tthrow new Meteor.Error('error-invalid-user', 'Invalid user', {\n\t\t\t\tmethod: 'dm.close',\n\t\t\t});\n\t\t}","sourceCodeStart":160,"sourceCodeEnd":196,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/f9d3ec372bb580fa8d036f94cf03925a478ef768/apps/meteor/server/api/v1/im.ts#L160-L196","documentation":"dmDeleteAction calls canAccessRoomIdAsync(room._id, userId) OR hasPermissionAsync(user, 'view-room-administration'). If both are false it throws error-not-allowed. Erasing a DM is therefore restricted to actual participants or workspace administrators with the view-room-administration permission.","triggerScenarios":"POST /api/v1/im.delete by a user who is neither a member of the target DM nor holds the 'view-room-administration' permission. Authenticated but unauthorized deletion attempt.","commonSituations":"A bot or integration trying to clean up DMs it did not create; a normal user attempting to delete another user's DM; permission 'view-room-administration' was revoked from the calling role.","solutions":["Call the endpoint as one of the two DM participants.","Grant the calling role/token owner the 'view-room-administration' permission if administrative deletion is intended.","Use an admin token (admin role) for cleanup automation.","Verify the target roomId actually belongs to a DM the caller is in (im.list)."],"exampleFix":"// before: bot token with no admin rights\nawait POST /api/v1/im.delete { roomId } // -> error-not-allowed\n\n// after: grant permission or use participant token\nawait POST /api/v1/im.delete { roomId } // called by a DM participant, or by a role with view-room-administration","handlingStrategy":"try-catch","validationCode":"// Pre-check access without mutating\nconst me = await api.get('/api/v1/me');\nconst subs = await api.get('/api/v1/im.list');\nconst isParticipant = subs.data.ims.some(im => im._id === roomId);\nconst isAdmin = me.data.roles?.includes('admin');\nif (!isParticipant && !isAdmin) throw new Error('Caller cannot delete this DM');","typeGuard":null,"tryCatchPattern":"try {\n  await api.post('/api/v1/im.delete', { roomId });\n} catch (e) {\n  if (e.response?.data?.error === 'error-not-allowed') {\n    // switch to a participant/admin token, or skip\n  } else throw e;\n}","preventionTips":["Run deletion automation as a participant or a role holding view-room-administration.","Audit the calling token's permissions before deployment.","Do not assume any authenticated user can erase arbitrary DMs."],"tags":["authorization","permission","direct-message","api"],"backgroundTag":null,"analyzedSha":"f9d3ec372bb580fa8d036f94cf03925a478ef768","analyzedAt":"2026-08-12T19:07:17.372Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}