redis/node-redis · error · Error
invalid nodeClientOptions for Sentinel
Error message
invalid nodeClientOptions for Sentinel
What it means
RedisSentinelInternal rejects nodeClientOptions that contain a url field. Sentinel discovers master/replica host:port from Sentinel itself (and applies nodeAddressMap), so a static url on node clients would conflict with the discovered topology and is not allowed. Use socket.host/socket.port or nodeAddressMap for address remapping instead.
Source
Thrown at packages/client/lib/sentinel/index.ts:864
this.#name = options.name;
this.#sentinelClientId = sentinelClientId;
this.#RESP = options.RESP;
this.#keyPrefix = options.keyPrefix;
this.#sentinelSeedNodes = Array.from(options.sentinelRootNodes);
// Initial root nodes start as a copy of the seed nodes; transform() later
// merges discovered nodes on top while preserving these seeds.
this.#sentinelRootNodes = Array.from(this.#sentinelSeedNodes);
this.#maxCommandRediscovers = options.maxCommandRediscovers ?? 16;
this.#masterPoolSize = options.masterPoolSize ?? 1;
this.#replicaPoolSize = options.replicaPoolSize ?? 0;
this.#nodeAddressMap = options.nodeAddressMap;
this.#scanInterval = options.scanInterval ?? 0;
this.#passthroughClientErrorEvents = options.passthroughClientErrorEvents ?? false;
this.#nodeClientOptions = (options.nodeClientOptions ? {...options.nodeClientOptions} : {}) as RedisClientOptions<M, F, S, RESP, TYPE_MAPPING, RedisTcpSocketOptions>;
if (this.#nodeClientOptions.url !== undefined) {
throw new Error("invalid nodeClientOptions for Sentinel");
}
// One fieldset registry across master/replica node clients: fieldsets registered before
// a failover must be transparently re-preparable on the promoted master's connections.
// (Sentinel-monitor clients use #sentinelClientOptions and never run HIMPORT.)
this.#nodeClientOptions.himportRegistry = new FieldsetRegistry();
if (options.clientSideCache) {
if (options.clientSideCache instanceof PooledClientSideCacheProvider) {
this.#clientSideCache = this.#nodeClientOptions.clientSideCache = options.clientSideCache;
} else {
const cscConfig = options.clientSideCache;
this.#clientSideCache = this.#nodeClientOptions.clientSideCache = new BasicPooledClientSideCache(cscConfig);
// this.#clientSideCache = this.#nodeClientOptions.clientSideCache = new PooledNoRedirectClientSideCache(cscConfig);
}
}
this.#sentinelClientOptions = options.sentinelClientOptions ? Object.assign({} as RedisClientOptions<typeof RedisSentinelModule, F, S, RESP, TYPE_MAPPING, RedisTcpSocketOptions>, options.sentinelClientOptions) : {};
this.#sentinelClientOptions.modules = RedisSentinelModule;View on GitHub (pinned to bb5beb5657)
Solutions
- Remove the url field from nodeClientOptions — set socket.host/socket.port only if needed (usually not; Sentinel provides addresses).
- Use nodeAddressMap to remap discovered Sentinel addresses to reachable host:port pairs (e.g. for Docker/TLS front-ends).
- Put connection-level options like TLS in nodeClientOptions.socket without a url.
- Destructure out url when reusing an existing options object: const { url, ...rest } = opts.
Example fix
// before
createSentinel({ nodeClientOptions: { url: 'redis://10.0.0.1:6379', socket: { tls: true } }, ... });
// after
createSentinel({ nodeClientOptions: { socket: { tls: true } }, nodeAddressMap: { '10.0.0.1:6379': 'redis.internal:6379' }, ... }); Defensive patterns
Strategy: validation
Validate before calling
function validateNodeOpts(opts) { if (opts.nodeClientOptions?.url !== undefined) throw new Error('nodeClientOptions.url is forbidden for Sentinel'); } Type guard
function sentinelNodeOptsValid(opts) { return opts.nodeClientOptions == null || opts.nodeClientOptions.url === undefined; } Try / catch
// Construction-time error: strip url before constructing.
Prevention
- Never put url in nodeClientOptions; let Sentinel discover addresses.
- Use nodeAddressMap to remap host:port for NAT/Docker/TLS.
- Destructure out url when reusing an options object: const { url, ...rest } = opts.
When it happens
Trigger: Constructing createSentinel({ nodeClientOptions: { url: 'redis://...' } }). The constructor copies nodeClientOptions and explicitly checks for the presence of .url, throwing if set.
Common situations: Copying a RedisClientOptions object that was built with { url } from a standalone client into the sentinel config; attempting to pin a node address via url instead of nodeAddressMap; sharing a TLS/socket config object that happens to carry url.
Related errors
- Client Side Caching is only supported with RESP3
- topologyRefreshOnReconnectionAttempt must be undefined, fals
- invalid sentinelClientOptions for Sentinel
- no valid master node
- Master Node Not Enumerated
AI-assisted analysis of redis/node-redis@bb5beb5657 (2026-08-03).
Data as JSON: /data/errors/2faac772b75f4319.json.
Report an issue: GitHub.