redis/node-redis · error · Error

no valid master node

Error message

no valid master node

What it means

Thrown by analyze() when parseNode(observed.masterData) returns undefined (sentinel/index.ts:1369). parseNode extracts host/port from the SENTINEL MASTER reply and rejects entries whose flags indicate the node is not a usable master; the trace logs `because ${observed.masterData.flags}`. So a sentinel was reached and replied, but the master it reported could not be parsed into a valid master node.

Source

Thrown at packages/client/lib/sentinel/index.ts:1371

        this.#trace(`observe: error ${err}`);
        this.emit('error', err);
      } finally {
        if (client !== undefined && client.isOpen) {
          this.#trace(`observe: destroying sentinel client`);
          client.destroy();
        }
      }
    }

    this.#trace(`observe: none of the sentinels are available`);
    throw new Error('None of the sentinels are available');
  }

  analyze(observed: Awaited<ReturnType<RedisSentinelInternal<M, F, S, RESP, TYPE_MAPPING>["observe"]>>) {
    let master = parseNode(observed.masterData);
    if (master === undefined) {
      this.#trace(`analyze: no valid master node because ${observed.masterData.flags}`);
      throw new Error("no valid master node");
    }

    if (master.host === observed.currentMaster?.host && master.port === observed.currentMaster?.port) {
      this.#trace(`analyze: master node hasn't changed from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`);
      master = undefined;
    } else {
      this.#trace(`analyze: master node has changed to ${master.host}:${master.port} from ${observed.currentMaster?.host}:${observed.currentMaster?.port}`);
    }

    let sentinel: RedisNode | undefined = observed.sentinelConnected;
    if (sentinel.host === observed.currentSentinel?.host && sentinel.port === observed.currentSentinel.port) {
      this.#trace(`analyze: sentinel node hasn't changed`);
      sentinel = undefined;
    } else {
      this.#trace(`analyze: sentinel node has changed to ${sentinel.host}:${sentinel.port}`);
    }

    const replicasToClose: Array<RedisNode> = [];

View on GitHub (pinned to bb5beb5657)

Solutions

  1. Confirm options.name exactly matches the master name in `sentinel masters` output on your sentinel.
  2. Run `redis-cli -h <sentinel> -p 26379 sentinel master <name>` and inspect the flags/host/port fields.
  3. If the master is flagged down, wait for failover to elect a new master and let the retry loop (maxCommandRediscovers) recover.
  4. Point sentinelRootNodes at sentinels that actually monitor the named master.
Defensive patterns

Strategy: validation

Validate before calling

// Validate the master name against a reachable sentinel before connecting.
import { createClient } from '@redis/client';
async function assertMasterMonitored(sentinelNode, name) {
  const c = createClient({ socket: sentinelNode, modules: undefined });
  c.on('error', () => {});
  await c.connect();
  try {
    const masters = await c.sentinel.sentinelMasters();
    if (!masters.some(m => m.name === name)) {
      throw new Error(`sentinel does not monitor master '${name}'`);
    }
  } finally {
    await c.destroy();
  }
}

Try / catch

try {
  await sentinel.connect();
} catch (e) {
  if (e instanceof Error && /no valid master node/.test(e.message)) {
    // options.name is wrong or master is failing over; surface to operator
  }
  throw e;
}

Prevention

When it happens

Trigger: The monitored name (options.name) does not match any master the sentinel monitors (SENTINEL MASTER returns an error/empty shape); the master is flagged down/disconnected in a way parseNode rejects; a sentinel version returning a malformed master record.

Common situations: Typo in options.name vs the actual master name configured in sentinel.conf; pointing at a sentinel that monitors a different deployment; sentinel mid-failover where the master record is transitional.

Related errors


AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03). Data as JSON: /data/errors/1aadfdc2a6edf07d.json. Report an issue: GitHub.