{"record":{"id":"61d8c9ccfceedd03","repo":"RocketChat/Rocket.Chat","slug":"not-authorized-61d8c9","errorCode":"not_authorized","errorMessage":"Unauthorized","messagePattern":"Unauthorized","errorType":"exception","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/meteor-methods/integrations/incoming/updateIncomingIntegration.ts","lineNumber":62,"sourceCode":"\nexport const updateIncomingIntegration = async (\n\tuserId: string,\n\tintegrationId: string,\n\tintegration: INewIncomingIntegration | IUpdateIncomingIntegration,\n): Promise<IIntegration | null> => {\n\tconst channels = validateChannels(integration.channel);\n\n\tlet currentIntegration;\n\n\tif (await hasPermissionAsync(userId, 'manage-incoming-integrations')) {\n\t\tcurrentIntegration = await Integrations.findOneById(integrationId);\n\t} else if (await hasPermissionAsync(userId, 'manage-own-incoming-integrations')) {\n\t\tcurrentIntegration = await Integrations.findOne({\n\t\t\t'_id': integrationId,\n\t\t\t'_createdBy._id': userId,\n\t\t});\n\t} else {\n\t\tthrow new Meteor.Error('not_authorized', 'Unauthorized', {\n\t\t\tmethod: 'updateIncomingIntegration',\n\t\t});\n\t}\n\n\tif (!currentIntegration) {\n\t\tthrow new Meteor.Error('error-invalid-integration', 'Invalid integration', {\n\t\t\tmethod: 'updateIncomingIntegration',\n\t\t});\n\t}\n\n\tconst oldScriptEngine = currentIntegration.scriptEngine;\n\tconst scriptEngine = integration.scriptEngine ?? oldScriptEngine ?? 'isolated-vm';\n\tif (\n\t\tintegration.script?.trim() &&\n\t\t(scriptEngine !== oldScriptEngine || integration.script?.trim() !== currentIntegration.script?.trim())\n\t) {\n\t\twrapExceptions(() => validateScriptEngine(scriptEngine)).catch((e) => {\n\t\t\tthrow new Meteor.Error(e.message);","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/meteor-methods/integrations/incoming/updateIncomingIntegration.ts#L44-L80","documentation":"Thrown by updateIncomingIntegration when the caller holds neither 'manage-incoming-integrations' nor 'manage-own-incoming-integrations'. With the first, the integration is looked up globally; with the second, only among records created by the caller; with neither, the method aborts with not_authorized before any update.","triggerScenarios":"A user whose integration permissions were revoked (but whose client UI still shows the edit screen) submits an update; a fresh user account without any integration role attempts an update.","commonSituations":"Role cleanup after team changes; permission grants not propagated to the client's cached roles until re-login; automation using a service account that was never given integration permissions.","solutions":["Grant the caller one of the two permissions: 'manage-incoming-integrations' for all records, 'manage-own-incoming-integrations' for their own","Re-login after permission changes so refreshed roles reach the client, then retry","For automated flows use POST /api/v1/integrations.update with an authorized admin token"],"exampleFix":"// before\nawait Meteor.callAsync('updateIncomingIntegration', id, payload); // caller lacks both permissions\n// after: call through an authorized service account via REST\nawait fetch(`${root}/api/v1/integrations.update`, { method: 'POST', headers: { 'X-Auth-Token': token, 'X-User-Id': uid }, body: JSON.stringify({ integrationId: id, ...payload }) });","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await Meteor.callAsync('updateIncomingIntegration', integrationId, integration);\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'not_authorized') { /* hide edit UI, prompt for permission or admin */ }\n}","preventionTips":["Gate integration edit screens on a client-visible permission check","Re-login after permission grants","Use an authorized REST token for automated updates"],"tags":["rocket-chat","incoming-integration","permissions","meteor-method"],"backgroundTag":"permission-denied","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}