{"record":{"id":"f0ca77c6719f6382","repo":"RocketChat/Rocket.Chat","slug":"invalid-url-it-doesn-t-exist-or-is-not-applicati","errorCode":null,"errorMessage":"Invalid url. It doesn't exist or is not \"application/zip\".","messagePattern":"Invalid url\\. It doesn't exist or is not \"application/zip\"\\.","errorType":"exception","errorClass":null,"httpStatus":400,"severity":"error","filePath":"apps/meteor/ee/server/apps/communication/rest.ts","lineNumber":327,"sourceCode":"\t\t\t\t\t\t\t\t\t.catch((cause) => {\n\t\t\t\t\t\t\t\t\t\tthrow new Error('App package download failed', { cause });\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\tApps.getMarketplaceClient()\n\t\t\t\t\t\t\t\t\t.fetch(`v1/apps/${this.bodyParams.appId}?appVersion=${this.bodyParams.version}`, {\n\t\t\t\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t\t\t\tAuthorization: `Bearer ${marketplaceToken}`,\n\t\t\t\t\t\t\t\t\t\t\t...headers,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t// SECURITY: user needs specific privileges to send this. Bypassing the SSRF check is okay for now.\n\t\t\t\t\t\t\t\t\t\tignoreSsrfValidation: true,\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t\t.catch((cause) => {\n\t\t\t\t\t\t\t\t\t\tthrow new Error('App metadata download failed', { cause });\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t]);\n\n\t\t\t\t\t\t\tif (downloadResponse.headers.get('content-type') !== 'application/zip') {\n\t\t\t\t\t\t\t\tthrow new Error('Invalid url. It doesn\\'t exist or is not \"application/zip\".');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbuff = Buffer.from(await downloadResponse.arrayBuffer());\n\t\t\t\t\t\t\tmarketplaceInfo = await marketplaceResponse.json();\n\n\t\t\t\t\t\t\t// Note: marketplace responds with an array of the marketplace info on the app, but it is expected\n\t\t\t\t\t\t\t// to always have one element since we are fetching a specific app version.\n\t\t\t\t\t\t\tif (!Array.isArray(marketplaceInfo) || marketplaceInfo?.length !== 1) {\n\t\t\t\t\t\t\t\torchestrator.getRocketChatLogger().error({ msg: 'Error getting app information from marketplace', marketplaceInfo });\n\t\t\t\t\t\t\t\tthrow new Error('Invalid response from the Marketplace');\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tpermissionsGranted = this.bodyParams.permissionsGranted;\n\t\t\t\t\t\t} catch (err: unknown) {\n\t\t\t\t\t\t\tlet message;\n\n\t\t\t\t\t\t\tif (err instanceof Error) {\n\t\t\t\t\t\t\t\torchestrator.getRocketChatLogger().error({ msg: 'Error installing app from marketplace:', err });","sourceCodeStart":309,"sourceCodeEnd":345,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/ee/server/apps/communication/rest.ts#L309-L345","documentation":"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()).","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nawait installFromMarketplace('invalid-app-id', '9.9.9');\n// -> Invalid url. It doesn't exist or is not \"application/zip\".\n\n// after: resolve an actually published version first\nconst info = await GET(`v1/apps/${appId}`);\nconst version = info.versions[0].version; // latest published\nawait installFromMarketplace(appId, version);","handlingStrategy":"validation","validationCode":"// Verify the version is published and downloadable before install\nasync function isDownloadableZip(appId: string, version: string, token: string): Promise<boolean> {\n  const res = await fetch(`https://marketplace.rocket.chat/v2/apps/${appId}/download/${version}?token=${token}`);\n  return res.headers.get('content-type') === 'application/zip';\n}","typeGuard":null,"tryCatchPattern":"try {\n  await installFromMarketplace(appId, version);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('application/zip')) {\n    // version/URL is wrong or a proxy rewrote the response — re-check version, do not retry as-is\n  }\n}","preventionTips":["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)."],"tags":["marketplace","app-install","content-type","validation","cloud","enterprise"],"backgroundTag":"unexpected-content-type","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","contentChangedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}