{"record":{"id":"4d9d4e30fe9ec28e","repo":"RocketChat/Rocket.Chat","slug":"not-authorized-4d9d4e","errorCode":null,"errorMessage":"not-authorized","messagePattern":"not-authorized","errorType":"exception","errorClass":"Error","httpStatus":400,"severity":"error","filePath":"apps/meteor/server/api/lib/integrations.ts","lineNumber":37,"sourceCode":"\nexport const findOneIntegration = async ({\n\tuserId,\n\tintegrationId,\n\tcreatedBy,\n}: {\n\tuserId: string;\n\tintegrationId: string;\n\tcreatedBy?: IUser['_id'];\n}): Promise<IIntegration> => {\n\tconst integration = await Integrations.findOneByIdAndCreatedByIfExists({\n\t\t_id: integrationId,\n\t\tcreatedBy,\n\t});\n\tif (!integration) {\n\t\tthrow new Error('The integration does not exists.');\n\t}\n\tif (!(await hasIntegrationsPermission(userId, integration))) {\n\t\tthrow new Error('not-authorized');\n\t}\n\treturn integration;\n};\n","sourceCodeStart":19,"sourceCodeEnd":41,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/api/lib/integrations.ts#L19-L41","documentation":"Thrown by fetchIntegration (apps/meteor/server/api/lib/integrations.ts) when the integration exists but hasIntegrationsPermission(userId, integration) returns false. That check passes only if the caller created the integration themselves or holds the incoming/outgoing integration management permissions (including channel-scoped permission for the channels the integration is configured on). It is a plain Error with the message 'not-authorized', so the REST layer returns it as an untyped failure rather than a Meteor permission error code.","triggerScenarios":"A non-owner user without manage-incoming-integrations / manage-outgoing-integrations permissions calls integrations.update, integrations.remove, etc. on an integration someone else created; or the caller has the global permission but lacks the channel-level permission for a channel the integration targets.","commonSituations":"A custom-bot admin role that was never granted the integration permissions; token belonging to a bot user rather than the integration owner; permission sets changed after the integration was created; enterprise workspace restricting integration management to a small group.","solutions":["Perform the operation with the integration creator's account or an admin token","Grant the caller's role manage-incoming-integrations / manage-outgoing-integrations (and the channel-scoped add-* permissions where relevant) in Administration > Permissions","Verify which user ID the auth token maps to — the permission check uses that user, not the body's userId"],"exampleFix":"// before: bot token without integration perms\nPOST /api/v1/integrations.remove { \"integrationId\": \"nS8ML...\" } // -> not-authorized\n\n// after: grant role the permission, or use owner/admin credentials\nPOST /api/v1/integrations.remove (Authorization: owner token) { \"integrationId\": \"nS8ML...\" }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await client.post('/api/v1/integrations.update', { integrationId, ...changes });\n} catch (e: any) {\n  const msg = e?.response?.data?.error ?? '';\n  if (msg === 'not-authorized' || e?.response?.status === 403) {\n    throw new ForbiddenError('caller is not the integration owner and lacks manage-*-integrations permissions');\n  }\n  throw e;\n}","preventionTips":["Run integration management jobs with the creator's or an admin's token","Pre-flight check role permissions (view-full-other-user-info style admin tooling) before bulk operations","Note the plain 'not-authorized' message — REST returns it without a typed error code"],"tags":["rest-api","integrations","permissions","authorization"],"backgroundTag":"permission-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}