RocketChat/Rocket.Chat · error · Meteor.Error

integration-type-must-be-outgoing

integration-type-must-be-outgoing

Error message

The integration type to replay must be an outgoing webhook.

What it means

Thrown by TriggerHandler.replay() when the integration passed in is not an outgoing webhook (type !== 'webhook-outgoing'). Replay re-executes a past outgoing-webhook delivery from integration history, so the operation is only defined for outgoing integrations; passing an incoming webhook, slash command, or a null integration triggers this Meteor.Error with code 'integration-type-must-be-outgoing'.

Source

Thrown at apps/meteor/server/lib/integrations/lib/triggerHandler.ts:800

							finished: true,
						});
					}
				}
			})
			.catch(async (err) => {
				outgoingLogger.error({ err });
				await updateHistory({
					historyId,
					step: 'after-http-call',
					httpError: err,
					httpResult: null,
				});
			});
	}

	async replay(integration: IOutgoingIntegration, history: IIntegrationHistory) {
		if (integration?.type !== 'webhook-outgoing') {
			throw new Meteor.Error('integration-type-must-be-outgoing', 'The integration type to replay must be an outgoing webhook.');
		}

		if (!history?.data) {
			throw new Meteor.Error('history-data-must-be-defined', 'The history data must be defined to replay an integration.');
		}

		const { event } = history;
		let owner;
		let message;
		let room;
		let user;

		if (history.data.owner?._id) {
			owner = await Users.findOneById(history.data.owner._id);
		}
		if (history.data.message_id) {
			message = await Messages.findOneById(history.data.message_id);
		}

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Fetch the integration first (GET /api/v1/integrations.get?integrationId=...) and confirm its type is 'webhook-outgoing' before calling replay
  2. Pass the correct integrationId of the outgoing webhook that owns the history entry
  3. If you meant to re-deliver an incoming webhook payload, resend the original HTTP POST to the incoming webhook URL instead of using replay

Example fix

// before
await sdk.post('integrations.replay', { integrationId, historyId }); // integrationId belongs to an incoming webhook

// after
const { integration } = await sdk.get('integrations.get', { integrationId });
if (integration.type === 'webhook-outgoing') {
  await sdk.post('integrations.replay', { integrationId, historyId });
}
Defensive patterns

Strategy: type-guard

Validate before calling

const { integration } = await sdk.get('integrations.get', { integrationId });
if (integration?.type !== 'webhook-outgoing') {
  throw new TypeError('replay is only valid for outgoing webhooks');
}

Type guard

const isOutgoingIntegration = (i?: { type?: string }): i is IOutgoingIntegration =>
  i?.type === 'webhook-outgoing';

Try / catch

try {
  await sdk.post('integrations.replay', { integrationId, historyId });
} catch (err: any) {
  if (err?.error === 'integration-type-must-be-outgoing') {
    // integrationId points at a non-outgoing integration; refetch and correct it
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling POST /api/v1/integrations.replay (or the server method behind the admin UI 'retry' action on an integration's history entry) with an integrationId whose record has type 'webhook-incoming' (or any non-outgoing type); or fetching the wrong integration record for the given historyId and replaying it.

Common situations: Automation scripts that iterate over all integrations and call replay on each; mixed workspaces where incoming and outgoing webhooks share similar names; passing the history's own id in place of integrationId so the lookup resolves to the wrong record.

Related errors


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