{"record":{"id":"95df6e12348c0a3c","repo":"redis/node-redis","slug":"master-node-not-enumerated","errorCode":null,"errorMessage":"Master Node Not Enumerated","messagePattern":"Master Node Not Enumerated","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/sentinel/index.ts","lineNumber":1758,"sourceCode":"\n      connected = true;\n\n      try {\n        const masterData = await client.sentinel.sentinelMaster(this.options.name);\n\n        const master = parseNode(masterData);\n        if (master === undefined) {\n          continue;\n        }\n\n        return master;\n      } finally {\n        client.destroy();\n      }\n    }\n\n    if (connected) {\n      throw new Error(\"Master Node Not Enumerated\");\n    }\n\n    throw new Error(\"couldn't connect to any sentinels\");\n  }\n\n  async getMasterClient() {\n    const master = await this.getMasterNode();\n    const socket = getMappedNode(master.host, master.port, this.options.nodeAddressMap);\n    return RedisClient.create({\n      ...this.options.nodeClientOptions,\n      socket: {\n        ...this.options.nodeClientOptions?.socket,\n        host: socket.host,\n        port: socket.port\n      }\n    });\n  }\n","sourceCodeStart":1740,"sourceCodeEnd":1776,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/sentinel/index.ts#L1740-L1776","documentation":"In `getMasterNode()`, the loop sets `connected = true` as soon as one sentinel responds, but if every responding sentinel yields a master record that `parseNode` rejects (undefined), none is returned and the method throws 'Master Node Not Enumerated'. This distinguishes 'sentinels reachable but do not know this master' from 'sentinels unreachable'.","triggerScenarios":"Passing a `name` that no monitored master matches; sentinel reachable but not configured to monitor the requested master name; master record flags make parseNode return undefined for all sentinels.","commonSituations":"Typo in the master `name` (e.g. 'mymaster' vs 'MyMaster'); pointing at a sentinel deployment that monitors a different master; sentinel that lost its master config.","solutions":["Verify `options.name` exactly matches the monitored master name (`SENTINEL masters` on a sentinel).","Confirm the sentinels you point at actually monitor that master.","Re-check the master record flags reported by the sentinel."],"exampleFix":"// before\nnew RedisSentinel({ name: 'MyMaster', rootNodes }, id); // wrong case\n// after\nnew RedisSentinel({ name: 'mymaster', rootNodes }, id); // matches SENTINEL monitor name","handlingStrategy":"validation","validationCode":"async function masterNameKnownBySentinel(rootNodes: { host: string; port: number }[], name: string, opts?: { password?: string }): Promise<boolean> {\n  for (const n of rootNodes) {\n    const c = new RedisClient({ modules: RedisSentinelModule, socket: { host: n.host, port: n.port }, password: opts?.password });\n    try {\n      await c.connect();\n      const masters = await c.sentinel.sentinelMasters();\n      c.destroy();\n      if (masters.some(m => m.name === name)) return true;\n    } catch { /* next */ }\n  }\n  return false;\n}","typeGuard":"function isValidMasterName(name: unknown): name is string {\n  return typeof name === 'string' && name.length > 0;\n}","tryCatchPattern":"try { return await sentinel.getMasterNode(); }\ncatch (e) {\n  if (String(e).includes('Master Node Not Enumerated')) {\n    throw new Error(`No sentinel monitors a master named '${opts.name}'`);\n  }\n  throw e;\n}","preventionTips":["Confirm options.name against `SENTINEL masters` output before boot.","Treat the master name as case-sensitive and keep it in one config source."],"tags":["sentinel","configuration","master-name","discovery"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}