RocketChat/Rocket.Chat · error · Meteor.Error
error-invalid-integration
error-invalid-integration
Error message
Invalid integration
What it means
Thrown by updateIncomingIntegration when the current integration record cannot be loaded. With 'manage-incoming-integrations' the lookup is Integrations.findOneById(integrationId); with 'manage-own-incoming-integrations' it additionally filters '_createdBy._id': userId. So it fires for a nonexistent id, an already-deleted integration, or an existing integration created by somebody else while the caller holds only the manage-own permission.
Source
Thrown at apps/meteor/server/meteor-methods/integrations/incoming/updateIncomingIntegration.ts:68
const channels = validateChannels(integration.channel);
let currentIntegration;
if (await hasPermissionAsync(userId, 'manage-incoming-integrations')) {
currentIntegration = await Integrations.findOneById(integrationId);
} else if (await hasPermissionAsync(userId, 'manage-own-incoming-integrations')) {
currentIntegration = await Integrations.findOne({
'_id': integrationId,
'_createdBy._id': userId,
});
} else {
throw new Meteor.Error('not_authorized', 'Unauthorized', {
method: 'updateIncomingIntegration',
});
}
if (!currentIntegration) {
throw new Meteor.Error('error-invalid-integration', 'Invalid integration', {
method: 'updateIncomingIntegration',
});
}
const oldScriptEngine = currentIntegration.scriptEngine;
const scriptEngine = integration.scriptEngine ?? oldScriptEngine ?? 'isolated-vm';
if (
integration.script?.trim() &&
(scriptEngine !== oldScriptEngine || integration.script?.trim() !== currentIntegration.script?.trim())
) {
wrapExceptions(() => validateScriptEngine(scriptEngine)).catch((e) => {
throw new Meteor.Error(e.message);
});
}
const isFrozen = isScriptEngineFrozen(scriptEngine);
// Default to transpiling with Babel for backwards compatibility; integrationsView on GitHub (pinned to b2c16d5842)
Solutions
- Re-fetch the integration list (GET /api/v1/integrations.list) and confirm the id still exists before updating
- If you hold only manage-own, edit only integrations you created; route other edits through an admin
- Treat as 'already removed' and refresh the UI if the record was deleted concurrently
Example fix
// before
await Meteor.callAsync('updateIncomingIntegration', staleId, payload); // -> error-invalid-integration
// after
const fresh = await Meteor.callAsync('listIncomingIntegrations');
const current = fresh.integrations?.find((i) => i._id === integrationId);
if (current) await Meteor.callAsync('updateIncomingIntegration', current._id, { ...payload, channel: current.channel.join(',') }); Defensive patterns
Strategy: validation
Validate before calling
const { integrations } = await Meteor.callAsync('listIncomingIntegrations');
const target = integrations.find((i) => i._id === integrationId);
if (!target) throw new Error('integration missing or not owned by caller');
await Meteor.callAsync('updateIncomingIntegration', integrationId, { ...integration, channel: integration.channel ?? target.channel.join(',') }); Try / catch
try {
await Meteor.callAsync('updateIncomingIntegration', integrationId, integration);
} catch (err) {
if (err instanceof Meteor.Error && err.error === 'error-invalid-integration') { /* refresh list; record deleted or owned by someone else */ }
} Prevention
- Refresh the record before editing (optimistic-concurrency style)
- For manage-own users, filter lists to createdBy = current user
- Copy ids programmatically, never by hand
When it happens
Trigger: Updating with a stale id after the integration was deleted elsewhere; manage-own user editing a teammate's webhook; id copied with a typo or trailing whitespace.
Common situations: Two admins editing concurrently (one deletes, the other saves); integrations list screens holding stale data after a workspace restore; cross-team ownership boundaries.
Related errors
- error-invalid-integration
- error-invalid-channel
- error-invalid-channel-start-with-chars
- error-invalid-username
- error-invalid-user
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/a7fdb8abdfebe89c.
Report an issue: GitHub.