{"record":{"id":"01fe99c657be08ac","repo":"n8n-io/n8n","slug":"bad-gateway-01fe99","errorCode":null,"errorMessage":"Bad Gateway","messagePattern":"Bad Gateway","errorType":"http","errorClass":null,"httpStatus":502,"severity":"warning","filePath":"packages/cli/src/controllers/telemetry.controller.ts","lineNumber":44,"sourceCode":"\t\t\t\t\treturn;\n\t\t\t\t},\n\t\t\t\tproxyRes: (proxyRes) => {\n\t\t\t\t\t// MCP app UIs call this cross-origin from sandboxed iframes. Upstream\n\t\t\t\t\t// may set CORS headers too, so normalize to one permissive value.\n\t\t\t\t\tfor (const header of [\n\t\t\t\t\t\t'access-control-allow-origin',\n\t\t\t\t\t\t'access-control-allow-credentials',\n\t\t\t\t\t\t'access-control-allow-methods',\n\t\t\t\t\t\t'access-control-allow-headers',\n\t\t\t\t\t\t'access-control-expose-headers',\n\t\t\t\t\t]) {\n\t\t\t\t\t\tdelete proxyRes.headers[header];\n\t\t\t\t\t}\n\t\t\t\t\tproxyRes.headers['access-control-allow-origin'] = '*';\n\t\t\t\t},\n\t\t\t\terror: (_error, _req, res) => {\n\t\t\t\t\tif ('writeHead' in res && !res.headersSent) {\n\t\t\t\t\t\tres.writeHead(502, { 'Access-Control-Allow-Origin': '*' });\n\t\t\t\t\t\tres.end('Bad Gateway');\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate applyCors(req: AuthenticatedRequest, res: Response) {\n\t\tres.setHeader('Access-Control-Allow-Origin', '*');\n\t\tres.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n\n\t\tconst requestedHeaders = req.headers['access-control-request-headers'];\n\t\tres.setHeader(\n\t\t\t'Access-Control-Allow-Headers',\n\t\t\ttypeof requestedHeaders === 'string' && requestedHeaders.length > 0\n\t\t\t\t? requestedHeaders\n\t\t\t\t: 'Content-Type, Authorization, anonymousId',\n\t\t);","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/cli/src/controllers/telemetry.controller.ts#L26-L62","documentation":"The telemetry/source-config controller proxies requests to api-rs.n8n.io. The http-proxy 'error' callback writes a raw 502 response with body 'Bad Gateway' whenever the proxy itself fails to reach the upstream (before any HTTP response is received).","triggerScenarios":"Any proxied telemetry/source-config request where the proxy emits an error event — upstream unreachable, DNS failure, connection reset, TLS handshake failure — and res.headersSent is still false.","commonSituations":"Air-gapped/offline instance; firewall/egress rules block outbound to api-rs.n8n.io; DNS misconfiguration; corporate proxy not configured for n8n.","solutions":["Allow outbound HTTPS to api-rs.n8n.io (and the RudderStack data plane) in firewall/egress rules.","If the instance is offline, disable diagnostics (N8N_DIAGNOSTICS_ENABLED=false) so the proxy is not exercised.","Route n8n through a corporate forward proxy (HTTP_PROXY/HTTPS_PROXY) if direct egress is blocked."],"exampleFix":"// before: offline/air-gapped instance still trying to proxy -> 502 Bad Gateway\n// after: disable diagnostics for offline instances\n// .env\nN8N_DIAGNOSTICS_ENABLED=false","handlingStrategy":"fallback","validationCode":"// Skip telemetry calls on offline instances.\nfunction shouldProxyTelemetry(env = process.env) {\n  return String(env.N8N_DIAGNOSTICS_ENABLED).toLowerCase() !== 'false';\n}","typeGuard":null,"tryCatchPattern":"// The 502 is a raw response, not a thrown JS error. Handle at the HTTP layer.\nif (res.status === 502 && res.body === 'Bad Gateway') {\n  // degrade telemetry silently; do not block the UI\n}","preventionTips":["Disable diagnostics on air-gapped instances.","Permit egress to api-rs.n8n.io or configure a forward proxy."],"tags":["telemetry","proxy","network","egress"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}