RocketChat/Rocket.Chat · error · Error

Failed to build external url

Error message

Failed to build external url

What it means

Thrown by AppClientOrchestrator.buildExternalUrl when GET /apps/buildExternalUrl returns a body without a `url` key. This endpoint builds a purchase/subscription redirect URL (marketplace checkout); if the server does not return the expected { url } field, the method cannot produce a valid redirect target and throws.

Source

Thrown at apps/meteor/client/apps/orchestrator.ts:144

		if ('app' in result) {
			return result.app;
		}
		throw new Error('App not found');
	}

	public async buildExternalUrl(appId: string, purchaseType: 'buy' | 'subscription' = 'buy', details = false): Promise<IAppExternalURL> {
		const result = await sdk.rest.get('/apps/buildExternalUrl', {
			appId,
			purchaseType,
			details: `${details}`,
		});

		if ('url' in result) {
			return result;
		}

		throw new Error('Failed to build external url');
	}

	public async buildExternalAppRequest(appId: string) {
		const result = await sdk.rest.get('/apps/buildExternalAppRequest', {
			appId,
		});

		if ('url' in result) {
			return result;
		}
		throw new Error('Failed to build App Request external url');
	}

	public async buildIncompatibleExternalUrl(appId: string, appVersion: string, action: string): Promise<IAppExternalURL> {
		const result = await sdk.rest.get('/apps/incompatibleModal', {
			appId,
			appVersion,
			action,

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Check the raw GET /apps/buildExternalUrl response body for the actual server reply.
  2. Ensure the marketplace is registered and the appId is a paid app that requires an external URL.
  3. Verify the server version supports the buildExternalUrl route.
  4. If the entitlement service is down, retry later or fall back to the in-app purchase flow.
Defensive patterns

Strategy: try-catch

Type guard

function hasUrlKey(r: unknown): r is { url: string } {
  return typeof r === 'object' && r !== null && 'url' in r;
}

Try / catch

try {
  const { url } = await orchestrator.buildExternalUrl(appId, purchaseType);
} catch (e) {
  if ((e as Error).message === 'Failed to build external url') {
    showMarketplaceConfigWarning();
  }
}

Prevention

When it happens

Trigger: Calling buildExternalUrl(appId, purchaseType, details) where the marketplace integration is misconfigured, the appId has no purchase flow, the server returns an error envelope with HTTP 200, or the buildExternalUrl route is unavailable in the deployed server version.

Common situations: Marketplace not configured (no 3CX/Marketplace registration); the app is free/no-op so no external URL is built; entitlement/billing service down; server version predates the buildExternalUrl endpoint; proxy returning an error page with 200.

Related errors


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