RocketChat/Rocket.Chat · error · Meteor.Error

history-data-must-be-defined

history-data-must-be-defined

Error message

The history data must be defined to replay an integration.

What it means

Thrown by TriggerHandler.replay() when the supplied history entry has no `data` field. Replay reconstructs the original trigger payload (event, message, room, owner) from history.data; without it there is nothing to re-send, so the server refuses with Meteor.Error code 'history-data-must-be-defined'.

Source

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

			})
			.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);
		}
		if (history.data.channel_id) {
			room = await Rooms.findOneById(history.data.channel_id);
		}
		if (history.data.user_id) {

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Select a history entry from a real execution that contains data (check GET /api/v1/integrations.history for the integration)
  2. Prefer the latest 'after-http-call' entry so owner/message/room resolve cleanly
  3. Do not construct history objects yourself; always replay by historyId returned by the history API

Example fix

// before
await replay(integration, history);

// after
if (!history?.data) {
  throw new Error('Pick a history entry that actually stored trigger data');
}
await replay(integration, history);
Defensive patterns

Strategy: validation

Validate before calling

if (!history?.data) {
  throw new Error('cannot replay: history entry has no stored trigger data');
}
await replay(integration, history);

Type guard

const hasReplayableData = (h?: IIntegrationHistory): h is IIntegrationHistory & { data: NonNullable<IIntegrationHistory['data']> } =>
  Boolean(h?.data);

Try / catch

try {
  await replay(integration, history);
} catch (err: any) {
  if (err?.error === 'history-data-must-be-defined') {
    // pick another historyId from integrations.history that has data
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling integrations.replay with a historyId whose history record was written with no data (early-abort steps like 'after-prepare-no-url_or_method' still store data, but hand-crafted or pruned records may not); passing a history object built manually instead of one loaded from the integration history collection; history entries from a very old Rocket.Chat version with a different schema.

Common situations: Scripts that pick the first history entry rather than a completed delivery; deployments where history documents were partially purged; replaying entries whose original run failed before payload mapping.

Understand the failure class

Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.

Related errors


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