redis/node-redis · error · Error
Client Side Caching is only supported with RESP3
Error message
Client Side Caching is only supported with RESP3
What it means
Redis Sentinel client-side caching (CSC / tracking) depends on RESP3 server-pushed invalidation messages, so the Sentinel constructor's #validateOptions refuses to enable it under any other protocol. The guard is `options.clientSideCache && (options.RESP ?? DEFAULT_RESP) !== 3`; since DEFAULT_RESP is 3, omitting RESP is fine, but explicitly setting RESP:2 (or any non-3 value) together with clientSideCache is rejected at construction time, before any connection is attempted.
Solutions
- Set `RESP: 3` on the same options object that sets `clientSideCache`.
- Omit `RESP` entirely so it defaults to 3, which satisfies the guard.
- Drop `clientSideCache` if you must stay on RESP:2.
Example fix
// before
new RedisSentinel({ name: 'mymaster', RESP: 2, clientSideCache: { ttl: 1000, maxEntries: 1000 } }, id);
// after
new RedisSentinel({ name: 'mymaster', RESP: 3, clientSideCache: { ttl: 1000, maxEntries: 1000 } }, id); Defensive patterns
Strategy: validation
Validate before calling
function assertCscResp3(opts: { clientSideCache?: unknown; RESP?: number }) {
const resp = opts.RESP ?? 3; // DEFAULT_RESP is 3
if (opts.clientSideCache && resp !== 3) {
throw new Error(`clientSideCache requires RESP 3, got RESP ${resp}`);
}
}
assertCscResp3(opts); // before `new RedisSentinel(opts, id)` Type guard
function isCscOptionsSafe(opts: { clientSideCache?: unknown; RESP?: number }): boolean {
return !opts.clientSideCache || (opts.RESP ?? 3) === 3;
} Try / catch
let sentinel;
try {
sentinel = new RedisSentinel(opts, id);
} catch (e) {
if (String(e).includes('Client Side Caching is only supported with RESP3')) {
opts = { ...opts, RESP: 3 };
sentinel = new RedisSentinel(opts, id);
} else throw e;
} Prevention
- Always pair clientSideCache with RESP: 3 in shared config builders.
- Centralize Sentinel option construction in one factory so the CSC/RESP invariant is enforced once.
When it happens
Trigger: Constructing `new RedisSentinel({ clientSideCache: {...}, RESP: 2 }, id)` or `new RedisSentinel({ clientSideCache: cacheProvider, RESP: 2 }, id)`. Triggers in the constructor, synchronously, regardless of whether the server actually supports RESP3.
Common situations: Copying a RESP:2 config from an existing standalone RedisClient into a Sentinel setup; standardizing on RESP:2 fleet-wide then opting into CSC; migrating from a non-Sentinel client that paired RESP:2 with a different caching strategy.
Related errors
- Client Side Caching is only supported with RESP3
- invalid nodeClientOptions for Sentinel
- invalid sentinelClientOptions for Sentinel
- Client Side Caching is only supported with RESP3
- emitInvalidate is only supported with RESP3
AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11).
Data as JSON: /api/errors/e0b83a62980286bf.
Report an issue: GitHub.
Appendix: source
Thrown at packages/client/lib/sentinel/index.ts:837
#connectPromise?: Promise<void>;
#maxCommandRediscovers: number;
readonly #pubSubProxy: PubSubProxy;
#scanTimer?: NodeJS.Timeout
#destroy = false;
#trace: (msg: string) => unknown = () => { };
#clientSideCache?: PooledClientSideCacheProvider;
get clientSideCache() {
return this.#clientSideCache;
}
#validateOptions(options?: RedisSentinelOptions<M, F, S, RESP, TYPE_MAPPING>) {
if (options?.clientSideCache && (options?.RESP ?? DEFAULT_RESP) !== 3) {
throw new Error('Client Side Caching is only supported with RESP3');
}
}
constructor(options: RedisSentinelOptions<M, F, S, RESP, TYPE_MAPPING>, sentinelClientId: string) {
super();
this.#validateOptions(options);
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;View on GitHub (pinned to 90fd0652bc)