RocketChat/Rocket.Chat · error
Invalid url. It doesn't exist or is not "application/zip".
Error message
Invalid url. It doesn't exist or is not "application/zip".
What it means
Thrown after a successful marketplace download when the response's Content-Type header is not exactly 'application/zip'. The installer expects the v2/apps/:id/download/:version endpoint to return the app package bytes as a zip; anything else (HTML error page, JSON error, redirect body) means the URL did not resolve to a real package and the buffer would be garbage. This is a protocol-level check before Buffer.from(await downloadResponse.arrayBuffer()).
Solutions
- Confirm the appId/version pair exists on the marketplace (GET v1/apps/:appId) and reinstall with a published version.
- Reproduce the download manually with curl -D - to inspect the actual status and Content-Type returned to the server.
- If a security appliance intercepts marketplace.rocket.chat, bypass it or add its CA so the real zip response is preserved.
- Retry later if the cloud was serving error bodies during an incident (the metadata check at 165 will usually co-trigger).
Example fix
// before
await installFromMarketplace('invalid-app-id', '9.9.9');
// -> Invalid url. It doesn't exist or is not "application/zip".
// after: resolve an actually published version first
const info = await GET(`v1/apps/${appId}`);
const version = info.versions[0].version; // latest published
await installFromMarketplace(appId, version); Defensive patterns
Strategy: validation
Validate before calling
// Verify the version is published and downloadable before install
async function isDownloadableZip(appId: string, version: string, token: string): Promise<boolean> {
const res = await fetch(`https://marketplace.rocket.chat/v2/apps/${appId}/download/${version}?token=${token}`);
return res.headers.get('content-type') === 'application/zip';
} Try / catch
try {
await installFromMarketplace(appId, version);
} catch (e) {
if (e instanceof Error && e.message.includes('application/zip')) {
// version/URL is wrong or a proxy rewrote the response — re-check version, do not retry as-is
}
} Prevention
- Only install versions listed by the marketplace info endpoint for the app.
- Bypass TLS-inspection proxies for marketplace domains or trust their CA properly.
- When wrapping the installer, distinguish content-type failures (permanent) from network failures (transient).
When it happens
Trigger: Marketplace returns 200 with text/html (proxy block page, cloud error page) or application/json (error envelope) instead of the zip stream; appVersion does not exist so the download URL serves a JSON 'not found' body with a 200 status; a middlebox rewrites the response. Only the Content-Type header is inspected, so status is not checked here.
Common situations: Passing a version that was never published or was removed from the marketplace; cloud incident serving error pages with 200; transparent proxy (Zscaler/Forcepoint) replacing downloads with an HTML interstitial; app pulled for policy reasons but version still referenced in scripts.
Related errors
- App metadata download failed
- App package download failed
- Invalid response from the Marketplace
- Marketplace_Failed_To_Fetch_Apps
- Marketplace_Failed_To_Fetch_Categories
AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18).
Data as JSON: /api/errors/f0ca77c6719f6382.
Report an issue: GitHub.
Appendix: source
Thrown at apps/meteor/ee/server/apps/communication/rest.ts:327
.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".');
}
buff = Buffer.from(await downloadResponse.arrayBuffer());
marketplaceInfo = await marketplaceResponse.json();
// Note: marketplace responds with an array of the marketplace info on the app, but it is expected
// to always have one element since we are fetching a specific app version.
if (!Array.isArray(marketplaceInfo) || marketplaceInfo?.length !== 1) {
orchestrator.getRocketChatLogger().error({ msg: 'Error getting app information from marketplace', marketplaceInfo });
throw new Error('Invalid response from the Marketplace');
}
permissionsGranted = this.bodyParams.permissionsGranted;
} catch (err: unknown) {
let message;
if (err instanceof Error) {
orchestrator.getRocketChatLogger().error({ msg: 'Error installing app from marketplace:', err });View on GitHub (pinned to b2c16d5842)