RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-integration
error-invalid-integration
Error message
Invalid integration
What it means
Thrown after the permission checks pass, when Integrations.removeByIdAndCreatedByIfExists({_id, [createdBy: userId]}) modifies nothing and returns null. The integration id does not exist — or, for callers holding only manage-own-outgoing-integrations, it exists but was created by someone else, because the createdBy filter silently excludes it.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/outgoing/deleteOutgoingIntegration.ts:38
});
}
const canManageAllIntegrations = await hasPermissionAsync(userId, 'manage-outgoing-integrations');
const canManageOwnIntegrations = !canManageAllIntegrations && (await hasPermissionAsync(userId, 'manage-own-outgoing-integrations'));
if (!canManageAllIntegrations && !canManageOwnIntegrations) {
throw new Meteor.Error('not_authorized', 'Unauthorized', {
method: 'deleteOutgoingIntegration',
});
}
const integration = await Integrations.removeByIdAndCreatedByIfExists({
_id: integrationId,
...(canManageOwnIntegrations && { createdBy: userId }),
});
if (!integration) {
throw new Meteor.Error('error-invalid-integration', 'Invalid integration', {
method: 'deleteOutgoingIntegration',
});
}
// Don't sending to IntegrationHistory listener since it don't waits for 'removed' events.
await IntegrationHistory.removeByIntegrationId(integrationId);
void notifyOnIntegrationChanged(integration, 'removed');
};
Meteor.methods<ServerMethods>({
async deleteOutgoingIntegration(integrationId) {
methodDeprecationLogger.method('deleteOutgoingIntegration', '9.0.0', '/v1/integrations.remove');
const userId = Meteor.userId();
if (!userId) {
throw new Meteor.Error('not_authorized', 'Unauthorized', {
method: 'deleteOutgoingIntegration',
});
}View on GitHub (pinned to b2c16d5842)
Solutions
- Confirm the integration still exists via GET /v1/integrations.list (type webhook-outgoing) and copy the exact _id
- If you hold only manage-own permissions, verify the integration's _createdBy._id is you — otherwise ask an admin to delete it
- Refresh the integration list in the UI and retry with the current id
Example fix
// before
await Meteor.callAsync('deleteOutgoingIntegration', integrationId);
// after: verify existence and ownership first
const res = await fetch('/api/v1/integrations.list?type=webhook-outgoing', { headers });
const { integrations } = await res.json();
const target = integrations.find((i) => i._id === integrationId);
if (!target) throw new Error('Integration not found — refresh the list');
await Meteor.callAsync('deleteOutgoingIntegration', integrationId); Defensive patterns
Strategy: validation
Validate before calling
// confirm the record exists (and is yours, if you only hold manage-own)
const res = await fetch('/api/v1/integrations.list?type=webhook-outgoing', { headers });
const { integrations } = await res.json();
const target = integrations.find((i) => i._id === integrationId);
if (!target) throw new Error('Integration not found');
if (!canManageAll && target._createdBy?._id !== uid) throw new Error('Not your integration'); Type guard
const isDeletableIntegration = ( i: IIntegration | null | undefined, uid: string, manageAll: boolean, ): i is IIntegration => !!i && (manageAll || i._createdBy?._id === uid);
Try / catch
try {
await Meteor.callAsync('deleteOutgoingIntegration', id);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-invalid-integration') {
// id is gone or not owned: refresh the list and reconcile local state; do not retry
return;
}
throw err;
} Prevention
- Always delete from a freshly loaded integration list
- With manage-own permissions, only show integrations created by the current user
- Treat repeat failures as already-deleted and sync your UI state
When it happens
Trigger: Passing a wrong or stale integrationId; double-delete races where another admin already removed it; owning only manage-own permissions while deleting an integration another user created.
Common situations: Admin UI holding a stale integration list after concurrent changes; users pasting integration ids they do not own.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- invalid_integration
- The integration does not exists.
- error-invalid-integration
- error-invalid-integration-history
- error-invalid-room
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/9e4e430a49d11d3b.
Report an issue: GitHub.