RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-permissions

error-invalid-permissions

Error message

Invalid permission for required Integration creation.

What it means

Thrown in validateOutgoing for events that do not use channels — roomArchived, roomCreated, userCreated — when the creating user lacks manage-outgoing-integrations. Because these events fire workspace-wide rather than per-channel, creating such integrations is restricted to users who can manage outgoing integrations; everyone else gets Meteor.Error code 'error-invalid-permissions'.

Source

Thrown at apps/meteor/server/lib/integrations/lib/validateOutgoingIntegration.ts:140

	let channels: string[] = [];
	if (outgoingEvents[integration.event].use.channel) {
		if (!Match.test(integration.channel, String)) {
			throw new Meteor.Error('error-invalid-channel', 'Invalid Channel', {
				function: 'validateOutgoing',
			});
		} else {
			channels = parseCSV(integration.channel);

			for (const channel of channels) {
				if (!validChannelChars.includes(channel[0]) && !scopedChannels.includes(channel.toLowerCase())) {
					throw new Meteor.Error('error-invalid-channel-start-with-chars', 'Invalid channel. Start with @ or #', {
						function: 'validateOutgoing',
					});
				}
			}
		}
	} else if (!(await hasPermissionAsync(userId, 'manage-outgoing-integrations'))) {
		throw new Meteor.Error('error-invalid-permissions', 'Invalid permission for required Integration creation.', {
			function: 'validateOutgoing',
		});
	}

	const user = await Users.findOne({ username: integration.username });

	if (!user) {
		throw new Meteor.Error('error-invalid-user', 'Invalid user (did you delete the `rocket.cat` user?)', { function: 'validateOutgoing' });
	}

	const integrationData: IOutgoingIntegration = {
		...integration,
		scriptEngine: integration.scriptEngine ?? 'isolated-vm',
		type: 'webhook-outgoing',
		channel: channels,
		userId: user._id,
		_createdAt: new Date(),
		_createdBy: await Users.findOne(userId, { projection: { username: 1 } }),

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Grant the creator's role manage-outgoing-integrations in Admin -> Permissions, then retry
  2. Or have an admin create the lifecycle integration and share the resulting token/URL with the team
  3. If you only need per-room events, switch to a channel-using event (e.g. sendMessage) which authorizes via room membership

Example fix

// before — non-admin creates a lifecycle integration
{ type: 'webhook-outgoing', event: 'roomCreated', ... }

// after — grant the permission first
// Admin -> Permissions -> creator's role -> manage-outgoing-integrations = On
Defensive patterns

Strategy: validation

Validate before calling

const EVENTS_WITHOUT_CHANNEL = ['roomArchived', 'roomCreated', 'userCreated'];
if (EVENTS_WITHOUT_CHANNEL.includes(event) && !(await hasPermissionAsync(userId, 'manage-outgoing-integrations'))) {
  throw new Error('only users with manage-outgoing-integrations may create this event type');
}

Prevention

When it happens

Trigger: A non-admin calls integrations.create with type 'webhook-outgoing' and event 'roomCreated', 'roomArchived', or 'userCreated' while their role lacks manage-outgoing-integrations. The else-branch of the use.channel check fires because there is no channel list to authorize against.

Common situations: Workspace-audit or provisioning bots that want room/user lifecycle events; users who successfully created sendMessage integrations (authorized via room membership) and assume all events work the same way.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/a34a0b2e8eb8677c. Report an issue: GitHub.