{"record":{"id":"6646a95a9b49774c","repo":"RocketChat/Rocket.Chat","slug":"integration-type-must-be-outgoing","errorCode":"integration-type-must-be-outgoing","errorMessage":"The integration type to replay must be an outgoing webhook.","messagePattern":"The integration type to replay must be an outgoing webhook\\.","errorType":"validation","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/integrations/lib/triggerHandler.ts","lineNumber":800,"sourceCode":"\t\t\t\t\t\t\tfinished: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(async (err) => {\n\t\t\t\toutgoingLogger.error({ err });\n\t\t\t\tawait updateHistory({\n\t\t\t\t\thistoryId,\n\t\t\t\t\tstep: 'after-http-call',\n\t\t\t\t\thttpError: err,\n\t\t\t\t\thttpResult: null,\n\t\t\t\t});\n\t\t\t});\n\t}\n\n\tasync replay(integration: IOutgoingIntegration, history: IIntegrationHistory) {\n\t\tif (integration?.type !== 'webhook-outgoing') {\n\t\t\tthrow new Meteor.Error('integration-type-must-be-outgoing', 'The integration type to replay must be an outgoing webhook.');\n\t\t}\n\n\t\tif (!history?.data) {\n\t\t\tthrow new Meteor.Error('history-data-must-be-defined', 'The history data must be defined to replay an integration.');\n\t\t}\n\n\t\tconst { event } = history;\n\t\tlet owner;\n\t\tlet message;\n\t\tlet room;\n\t\tlet user;\n\n\t\tif (history.data.owner?._id) {\n\t\t\towner = await Users.findOneById(history.data.owner._id);\n\t\t}\n\t\tif (history.data.message_id) {\n\t\t\tmessage = await Messages.findOneById(history.data.message_id);\n\t\t}","sourceCodeStart":782,"sourceCodeEnd":818,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/integrations/lib/triggerHandler.ts#L782-L818","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Fetch the integration first (GET /api/v1/integrations.get?integrationId=...) and confirm its type is 'webhook-outgoing' before calling replay","Pass the correct integrationId of the outgoing webhook that owns the history entry","If you meant to re-deliver an incoming webhook payload, resend the original HTTP POST to the incoming webhook URL instead of using replay"],"exampleFix":"// before\nawait sdk.post('integrations.replay', { integrationId, historyId }); // integrationId belongs to an incoming webhook\n\n// after\nconst { integration } = await sdk.get('integrations.get', { integrationId });\nif (integration.type === 'webhook-outgoing') {\n  await sdk.post('integrations.replay', { integrationId, historyId });\n}","handlingStrategy":"type-guard","validationCode":"const { integration } = await sdk.get('integrations.get', { integrationId });\nif (integration?.type !== 'webhook-outgoing') {\n  throw new TypeError('replay is only valid for outgoing webhooks');\n}","typeGuard":"const isOutgoingIntegration = (i?: { type?: string }): i is IOutgoingIntegration =>\n  i?.type === 'webhook-outgoing';","tryCatchPattern":"try {\n  await sdk.post('integrations.replay', { integrationId, historyId });\n} catch (err: any) {\n  if (err?.error === 'integration-type-must-be-outgoing') {\n    // integrationId points at a non-outgoing integration; refetch and correct it\n  }\n  throw err;\n}","preventionTips":["Filter integration lists by type === 'webhook-outgoing' before offering a replay action","Pair historyId with the integrationId returned by the history query so records cannot be mismatched"],"tags":["integrations","outgoing-webhook","replay","rest-api"],"backgroundTag":"wrong-resource-type","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}