{"record":{"id":"b8ae4ef02d6073e9","repo":"louislam/uptime-kuma","slug":"all-errors-length-nodes-failed-because-errors","errorCode":null,"errorMessage":"All ${errors.length} nodes failed because ${errors.join(\"; \")}","messagePattern":"All (.+?) nodes failed because (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/monitor-types/rabbitmq.js","lineNumber":46,"sourceCode":"            const nodeIndex = i + 1;\n\n            try {\n                await this.checkSingleNode(monitor, baseUrl, `${nodeIndex}/${baseUrls.length}`);\n                // If checkSingleNode succeeds (doesn't throw), set heartbeat to UP\n                heartbeat.status = UP;\n                heartbeat.msg =\n                    baseUrls.length === 1\n                        ? \"Node is reachable and there are no alerts in the cluster\"\n                        : `One of the ${baseUrls.length} nodes is reachable and there are no alerts in the cluster`;\n                return;\n            } catch (error) {\n                log.warn(this.name, `Node ${nodeIndex}: ${error.message}`);\n                errors.push(`Node ${nodeIndex}: ${error.message}`);\n            }\n        }\n\n        // If we reach here, all nodes failed\n        throw new Error(`All ${errors.length} nodes failed because ${errors.join(\"; \")}`);\n    }\n\n    /**\n     * Check a single RabbitMQ node\n     * @param {object} monitor Monitor configuration\n     * @param {string} baseUrl Base URL of the RabbitMQ node\n     * @param {string} nodeInfo Node index info for logging (e.g., \"1/3\")\n     * @returns {Promise<void>}\n     * @throws {Error} If the node check fails\n     */\n    async checkSingleNode(monitor, baseUrl, nodeInfo) {\n        // Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com\n        let normalizedUrl = baseUrl;\n        if (!normalizedUrl.endsWith(\"/\")) {\n            normalizedUrl += \"/\";\n        }\n\n        const options = {","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/louislam/uptime-kuma/blob/6b5ea0155793e666666745fb8d6fef1e829543a2/server/monitor-types/rabbitmq.js#L28-L64","documentation":"The check() loop iterates every node and calls checkSingleNode; each failure is caught, logged at warn, and appended to an errors array as 'Node N: <message>'. If the loop completes without any success, no single node was reachable, so it throws an aggregate error summarizing the count and each per-node failure joined by '; '. This is the all-nodes-down terminal condition.","triggerScenarios":"Every node in baseUrls failed checkSingleNode — each either returned non-200, returned 503 with a reason, timed out, or threw a network error. The message lists all of them so the operator can see the full pattern rather than only the last failure.","commonSituations":"RabbitMQ cluster fully down, network partition isolating all nodes, wrong credentials applied to every node (each 401/403), or the management plugin disabled on all nodes (each 404).","solutions":["Read each 'Node N: ...' segment; if all share the same cause (e.g. 401), fix that shared cause first.","Verify each node's management API responds: curl -u user:pass http://node:15672/api/aliveness-test/%2F.","Check credentials, network reachability, and that the rabbitmq_management plugin is enabled on every node.","If only some nodes are truly down, consider removing the permanently-unreachable ones from the list."],"exampleFix":"# before\nAll 3 nodes failed because Node 1: 401 - Unauthorized; Node 2: 401 - Unauthorized; Node 3: 401 - Unauthorized\n# after  (correct the shared credential)\nUpdate monitor.rabbitmqUsername / rabbitmqPassword","handlingStrategy":"try-catch","validationCode":"// Pre-flight: probe each node independently so the aggregate error never fires.\nasync function probeAllNodes(monitor) {\n  const nodes = parseRabbitNodes(monitor.rabbitmqNodes);\n  const results = await Promise.allSettled(\n    nodes.map(url => checkSingleNode(monitor, url, url))\n  );\n  if (!results.some(r => r.status === 'fulfilled')) {\n    const reasons = results.map((r, i) => `Node ${i+1}: ${r.reason.message}`).join('; ');\n    throw new Error(`All ${results.length} nodes failed because ${reasons}`);\n  }\n}","typeGuard":"function allFailed(errors) { return Array.isArray(errors) && errors.length > 0 && errors.length === totalNodes; }","tryCatchPattern":"try {\n  await rabbitmqMonitor.check(monitor, heartbeat, server);\n} catch (e) {\n  if (/^All \\d+ nodes failed because/.test(e.message)) {\n    // surface per-node breakdown; treat as cluster-wide outage, page operator\n    heartbeat.status = DOWN;\n    heartbeat.msg = e.message;\n  }\n}","preventionTips":["Treat any node success as cluster healthy; only alert when all fail.","Log per-node outcomes for trend analysis.","Add synthetic checks per node to localise partial outages."],"tags":["rabbitmq","aggregate-error","cluster","network"],"backgroundTag":null,"analyzedSha":"6b5ea0155793e666666745fb8d6fef1e829543a2","analyzedAt":"2026-08-12T23:42:12.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}