RocketChat/Rocket.Chat · error

Invalid service URL

Error message

Invalid service URL

What it means

For a valid external-service trigger, the first action's params are destructured with defaults (serviceTimeout 5000, serviceFallbackMessage 'trigger-default-fallback-message') but serviceUrl has no default; when it is missing or empty the route throws 'Invalid service URL' and the outbound call never happens.

Solutions

  1. Edit the trigger and set the Service URL on its external-service action, then save.
  2. Re-fetch the trigger and confirm actions[0].params.serviceUrl is non-empty before calling.
  3. Validate the same URL with POST /api/v1/livechat/triggers/external-service/test to confirm reachability and response shape.

Example fix

// before: actions[0].params = { serviceTimeout: 5000 }  // no serviceUrl
// after:  actions[0].params = {
//   serviceUrl: 'https://svc.example.com/trigger',
//   serviceTimeout: 5000,
//   serviceFallbackMessage: 'One moment please',
// }
Defensive patterns

Strategy: validation

Validate before calling

const { triggers } = await api.get('/v1/livechat/triggers', { params: { count: 0 } });
const trigger = triggers.find((t) => t._id === triggerId);
const serviceUrl = trigger?.actions?.[0]?.params?.serviceUrl;
if (!serviceUrl) throw new Error('Trigger action has no serviceUrl configured');
await api.post(`/v1/livechat/triggers/${triggerId}/external-service/call`, body);

Type guard

const hasServiceUrl = (t: { actions?: { params?: { serviceUrl?: string } }[] } | undefined): boolean =>
  typeof t?.actions?.[0]?.params?.serviceUrl === 'string' && t.actions[0].params.serviceUrl.length > 0;

Try / catch

try {
  await api.post(`/v1/livechat/triggers/${triggerId}/external-service/call`, body);
} catch (e) {
  if (e?.response?.data?.error === 'Invalid service URL') {
    // set actions[0].params.serviceUrl on the trigger, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: Trigger whose external-service action was saved without a Service URL (empty or omitted serviceUrl), then POST /api/v1/livechat/triggers/<id>/external-service/call is hit.

Common situations: Trigger form submitted with the URL field cleared; triggers imported or migrated with params dropped; URL stored under a different key by older tooling.

Related errors


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

Appendix: source

Thrown at apps/meteor/ee/server/api/v1/omnichannel/triggers.ts:93

		async post() {
			const { _id: triggerId } = this.urlParams;
			const { token: visitorToken, extraData } = this.bodyParams;

			const trigger = await LivechatTrigger.findOneById(triggerId);

			if (!trigger) {
				throw new Error('Invalid trigger');
			}

			if (!trigger?.actions.length || !isExternalServiceTrigger(trigger)) {
				throw new Error('Trigger is not configured to use an external service');
			}

			const { params: { serviceTimeout = 5000, serviceUrl, serviceFallbackMessage = 'trigger-default-fallback-message' } = {} } =
				trigger.actions[0];

			if (!serviceUrl) {
				throw new Error('Invalid service URL');
			}

			const token = settings.get<string>('Livechat_secret_token');

			if (!token) {
				throw new Error('Livechat secret token is not configured');
			}

			const body = {
				metadata: extraData,
				visitorToken,
			};

			const headers = {
				'Accept': 'application/json',
				'Content-Type': 'application/json',
				'X-RocketChat-Livechat-Token': token,
			};

View on GitHub (pinned to b2c16d5842)