{"record":{"id":"1aadfdc2a6edf07d","repo":"redis/node-redis","slug":"no-valid-master-node","errorCode":null,"errorMessage":"no valid master node","messagePattern":"no valid master node","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/client/lib/sentinel/index.ts","lineNumber":1371,"sourceCode":"        this.#trace(`observe: error ${err}`);\n        this.emit('error', err);\n      } finally {\n        if (client !== undefined && client.isOpen) {\n          this.#trace(`observe: destroying sentinel client`);\n          client.destroy();\n        }\n      }\n    }\n\n    this.#trace(`observe: none of the sentinels are available`);\n    throw new Error('None of the sentinels are available');\n  }\n\n  analyze(observed: Awaited<ReturnType<RedisSentinelInternal<M, F, S, RESP, TYPE_MAPPING>[\"observe\"]>>) {\n    let master = parseNode(observed.masterData);\n    if (master === undefined) {\n      this.#trace(`analyze: no valid master node because ${observed.masterData.flags}`);\n      throw new Error(\"no valid master node\");\n    }\n\n    if (master.host === observed.currentMaster?.host && master.port === observed.currentMaster?.port) {\n      this.#trace(`analyze: master node hasn't changed from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`);\n      master = undefined;\n    } else {\n      this.#trace(`analyze: master node has changed to ${master.host}:${master.port} from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`);\n    }\n\n    let sentinel: RedisNode | undefined = observed.sentinelConnected;\n    if (sentinel.host === observed.currentSentinel?.host && sentinel.port === observed.currentSentinel.port) {\n      this.#trace(`analyze: sentinel node hasn't changed`);\n      sentinel = undefined;\n    } else {\n      this.#trace(`analyze: sentinel node has changed to ${sentinel.host}:${sentinel.port}`);\n    }\n\n    const replicasToClose: Array<RedisNode> = [];","sourceCodeStart":1353,"sourceCodeEnd":1389,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/sentinel/index.ts#L1353-L1389","documentation":"`analyze()` runs `parseNode` on the master record returned by Sentinel; if the record's flags mark the master as not usable (e.g. s_down, o_down, disconnected), parseNode returns undefined and analyze throws rather than acting on a master that cannot serve. It guards the failover decision step.","triggerScenarios":"Sentinel returned a master record whose flags fail parseNode's validity check — typically because the master is reported down or a failover is mid-flight and no healthy master is elected yet.","commonSituations":"Failover in progress (old master flagged down, new not yet promoted); sentinel itself stale or split-brain; master crashed and no failover completed.","solutions":["Wait for Sentinel to complete failover and re-run; this is often transient.","Confirm Sentinel quorum and that a new master was actually promoted.","Check the master's health directly and Sentinel's `SENTINEL master <name>` flags.","Ensure replica promotion is enabled and replicas exist to fail over to."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"async function waitForMaster(sentinel: { getMasterNode(): Promise<unknown> }, attempts = 10) {\n  for (let i = 0; i < attempts; i++) {\n    try { return await sentinel.getMasterNode(); }\n    catch (e) {\n      if (String(e).includes('no valid master node') && i < attempts - 1) {\n        await new Promise(r => setTimeout(r, 1000 * (i + 1)));\n        continue;\n      }\n      throw e;\n    }\n  }\n  throw new Error('master never became valid');\n}","preventionTips":["Treat 'no valid master node' as transient during failover and retry with backoff.","Ensure Sentinel quorum and replica promotion are configured so failover completes."],"tags":["sentinel","failover","master","topology"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}