RocketChat/Rocket.Chat · error · MarketplaceConnectionError

Marketplace_Bad_Marketplace_Connection

Error message

Marketplace_Bad_Marketplace_Connection

What it means

Thrown by fetchMarketplaceCategories when the marketplace client fetch to v1/categories throws at the network level. Same pattern as the apps variant: CloudOfflineLicenseError is rethrown as-is; any other throw becomes MarketplaceConnectionError('Marketplace_Bad_Marketplace_Connection'). HTTP error statuses are handled downstream, not here.

Source

Thrown at apps/meteor/ee/server/apps/marketplace/fetchMarketplaceCategories.ts:51

	if (token) {
		headers.Authorization = `Bearer ${token}`;
	}

	let request;
	try {
		request = await Apps.getMarketplaceClient().fetch(`v1/categories`, {
			headers,
			ignoreSsrfValidation: false,
			allowList: settings.get<string>('SSRF_Allowlist'),
		});
	} catch (error) {
		// Offline (air-gapped) licenses reject before any request is made; keep the
		// typed error so the REST layer can report the real reason instead of a
		// generic connectivity failure.
		if (error instanceof CloudOfflineLicenseError) {
			throw error;
		}
		throw new MarketplaceConnectionError('Marketplace_Bad_Marketplace_Connection');
	}

	if (request.status === 200) {
		const response = await request.json();
		fetchMarketplaceCategoriesSchema.parse(response);
		return response;
	}

	const response = await request.json();

	Apps.getRocketChatLogger().error({ msg: 'Error fetching marketplace categories', status: request.status, response });

	// TODO: Refactor cloud to return a proper error code on unsupported version
	if (request.status === 426 && 'errorMsg' in response && response.errorMsg === 'unsupported version') {
		throw new MarketplaceUnsupportedVersionError();
	}

	const INTERNAL_MARKETPLACE_ERROR_CODES = [189, 266];

View on GitHub (pinned to f9d3ec372b)

Solutions

  1. Verify outbound network access to the marketplace host.
  2. Configure HTTPS_PROXY if behind a corporate proxy and restart.
  3. Add the marketplace host to SSRF_Allowlist if SSRF validation applies.
  4. Handle CloudOfflineLicenseError separately if running an offline license intentionally.
  5. Retry after restoring connectivity.
Defensive patterns

Strategy: retry

Validate before calling

async function canReachMarketplaceHost(): Promise<boolean> {
  try {
    await Apps.getMarketplaceClient().fetch('v1/categories', { ignoreSsrfValidation: false });
    return true;
  } catch { return false; }
}

Type guard

import { MarketplaceConnectionError } from './marketplaceErrors';
import { CloudOfflineLicenseError } from '../../../../lib/errors/CloudOfflineLicenseError';

const isMarketplaceConnectionError = (e: unknown): e is MarketplaceConnectionError =>
  e instanceof MarketplaceConnectionError;

const isOfflineLicenseError = (e: unknown): e is CloudOfflineLicenseError =>
  e instanceof CloudOfflineLicenseError;

Try / catch

try {
  return await fetchMarketplaceCategories();
} catch (e) {
  if (e instanceof CloudOfflineLicenseError) return [];
  if (e instanceof MarketplaceConnectionError) {
    return await retryWithBackoff(() => fetchMarketplaceCategories());
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling fetchMarketplaceCategories() with no network route to the marketplace, DNS failure, TLS handshake failure, or request abort. The offline-license branch fires when an air-gapped license blocks the call before it is made.

Common situations: Air-gapped deployment; proxy/firewall blocking the marketplace host; SSRF_Allowlist misconfiguration; DNS outage; offline license in an online-expected flow.

Related errors


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