{"record":{"id":"e0b83a62980286bf","repo":"redis/node-redis","slug":"client-side-caching-is-only-supported-with-resp3-e0b83a","errorCode":null,"errorMessage":"Client Side Caching is only supported with RESP3","messagePattern":"Client Side Caching is only supported with RESP3","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/sentinel/index.ts","lineNumber":837,"sourceCode":"\n  #connectPromise?: Promise<void>;\n  #maxCommandRediscovers: number;\n  readonly #pubSubProxy: PubSubProxy;\n\n  #scanTimer?: NodeJS.Timeout\n\n  #destroy = false;\n\n  #trace: (msg: string) => unknown = () => { };\n\n  #clientSideCache?: PooledClientSideCacheProvider;\n  get clientSideCache() {\n    return this.#clientSideCache;\n  }\n\n  #validateOptions(options?: RedisSentinelOptions<M, F, S, RESP, TYPE_MAPPING>) {\n    if (options?.clientSideCache && (options?.RESP ?? DEFAULT_RESP) !== 3) {\n      throw new Error('Client Side Caching is only supported with RESP3');\n    }\n  }\n\n  constructor(options: RedisSentinelOptions<M, F, S, RESP, TYPE_MAPPING>, sentinelClientId: string) {\n    super();\n\n    this.#validateOptions(options);\n\n    this.#name = options.name;\n    this.#sentinelClientId = sentinelClientId;\n\n    this.#RESP = options.RESP;\n    this.#keyPrefix = options.keyPrefix;\n    this.#sentinelSeedNodes = Array.from(options.sentinelRootNodes);\n    // Initial root nodes start as a copy of the seed nodes; transform() later\n    // merges discovered nodes on top while preserving these seeds.\n    this.#sentinelRootNodes = Array.from(this.#sentinelSeedNodes);\n    this.#maxCommandRediscovers = options.maxCommandRediscovers ?? 16;","sourceCodeStart":819,"sourceCodeEnd":855,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/sentinel/index.ts#L819-L855","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nnew RedisSentinel({ name: 'mymaster', RESP: 2, clientSideCache: { ttl: 1000, maxEntries: 1000 } }, id);\n// after\nnew RedisSentinel({ name: 'mymaster', RESP: 3, clientSideCache: { ttl: 1000, maxEntries: 1000 } }, id);","handlingStrategy":"validation","validationCode":"function assertCscResp3(opts: { clientSideCache?: unknown; RESP?: number }) {\n  const resp = opts.RESP ?? 3; // DEFAULT_RESP is 3\n  if (opts.clientSideCache && resp !== 3) {\n    throw new Error(`clientSideCache requires RESP 3, got RESP ${resp}`);\n  }\n}\nassertCscResp3(opts); // before `new RedisSentinel(opts, id)`","typeGuard":"function isCscOptionsSafe(opts: { clientSideCache?: unknown; RESP?: number }): boolean {\n  return !opts.clientSideCache || (opts.RESP ?? 3) === 3;\n}","tryCatchPattern":"let sentinel;\ntry {\n  sentinel = new RedisSentinel(opts, id);\n} catch (e) {\n  if (String(e).includes('Client Side Caching is only supported with RESP3')) {\n    opts = { ...opts, RESP: 3 };\n    sentinel = new RedisSentinel(opts, id);\n  } else throw e;\n}","preventionTips":["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."],"tags":["sentinel","client-side-caching","resp3","configuration","constructor"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}