RocketChat/Rocket.Chat · error · Error
App package download failed
Error message
App package download failed
What it means
Thrown during marketplace app install (POST /apps with appId+version+marketplace) when the call to fetch the app zip from v2/apps/{appId}/download/{version} rejects. The original rejection is preserved as the cause (new Error('App package download failed', { cause })). The route runs both the package download and the metadata fetch in parallel via Promise.all, so a failure on either short-circuits.
Source
Thrown at apps/meteor/ee/server/apps/communication/rest.ts:310
} catch (err: any) {
orchestrator.getRocketChatLogger().error({ msg: 'Error fetching App from URL:', err });
return API.v1.internalError();
}
} else if ('appId' in this.bodyParams && this.bodyParams.appId && this.bodyParams.marketplace && this.bodyParams.version) {
const headers = getDefaultHeaders();
try {
const downloadToken = await getWorkspaceAccessToken(true, 'marketplace:download', false);
const marketplaceToken = await getWorkspaceAccessToken();
const [downloadResponse, marketplaceResponse] = await Promise.all([
Apps.getMarketplaceClient()
.fetch(`v2/apps/${this.bodyParams.appId}/download/${this.bodyParams.version}?token=${downloadToken}`, {
headers,
// SECURITY: user needs specific privileges to send this. Bypassing the SSRF check is okay for now.
ignoreSsrfValidation: true,
})
.catch((cause) => {
throw new Error('App package download failed', { cause });
}),
Apps.getMarketplaceClient()
.fetch(`v1/apps/${this.bodyParams.appId}?appVersion=${this.bodyParams.version}`, {
headers: {
Authorization: `Bearer ${marketplaceToken}`,
...headers,
},
// SECURITY: user needs specific privileges to send this. Bypassing the SSRF check is okay for now.
ignoreSsrfValidation: true,
})
.catch((cause) => {
throw new Error('App metadata download failed', { cause });
}),
]);
if (downloadResponse.headers.get('content-type') !== 'application/zip') {
throw new Error('Invalid url. It doesn\'t exist or is not "application/zip".');
}View on GitHub (pinned to f9d3ec372b)
Solutions
- Check outbound connectivity from the server to the marketplace host (verify Site_Url and proxy settings).
- Confirm the workspace is registered (Administration > Connectivity Services) so getWorkspaceAccessToken returns a valid download token.
- Retry the install; transient marketplace failures often resolve on retry.
- Verify the requested appId/version exist on the marketplace; an unpublished or yanked version will 404.
- Inspect the preserved cause in logs (the logged err includes the original fetch error) for the real HTTP status.
Defensive patterns
Strategy: try-catch
Validate before calling
async function canReachMarketplace(): Promise<boolean> {
try {
const res = await fetch('https://marketplace.rocket.chat/health', { method: 'GET' });
return res.ok;
} catch { return false; }
}
if (!await canReachMarketplace()) {
throw new Error('Marketplace unreachable; cannot download app package');
} Type guard
const isInstallPayload = (body: unknown): body is { appId: string; version: string; marketplace: true } =>
typeof body === 'object' &&
typeof (body as any)?.appId === 'string' &&
typeof (body as any)?.version === 'string' &&
(body as any)?.marketplace === true; Try / catch
try {
await installMarketplaceApp(appId, version);
} catch (e) {
if (e instanceof Error && e.message === 'App package download failed') {
// e.cause holds the original fetch error - inspect it
console.error('Underlying cause:', (e as Error & { cause?: Error }).cause);
retryWithBackoff();
}
} Prevention
- Ensure workspace registration is active before install (valid download token).
- Verify outbound connectivity and proxy config in advance.
- Retry install once after a short backoff for transient marketplace errors.
- Log e.cause, not just e.message, when this error surfaces.
When it happens
Trigger: POST /api/v1/apps with body { appId, version, marketplace: true } while the workspace cannot reach the marketplace, the download token is invalid/expired, the version does not exist on the marketplace, or the marketplace host returns a non-2xx/throwing response for the download URL.
Common situations: Air-gapped or proxy-restricted server without outbound access to the marketplace; expired/missing workspace registration token (getWorkspaceAccessToken for the download scope failed silently); user requested a version that was unpublished; transient marketplace outage or DNS failure.
Related errors
- App metadata download failed
- Invalid url. It doesn't exist or is not "application/zip".
- Invalid response from the Marketplace
- result.error
- Invalid response from API
AI-assisted analysis of RocketChat/Rocket.Chat@f9d3ec372b (2026-08-12).
Data as JSON: /api/errors/3af4cf13b5cf4415.
Report an issue: GitHub.