Description
Description
Environment:
- client: node 18 (public.ecr.aws/docker/library/node:18-alpine)
- redis server: AWS elasticache
- engine version: 6.2.6
- 2 shards; 2 nodes per shard
We're getting this error - I think it's intermittent ie it works maybe even a lot of the time:
Stacktrace (redactions using xxx
):
TypeError: Cannot read properties of undefined (reading 'replicas')
at RedisClusterSlots.getSlotRandomNode (/server/node_modules/@redis/client/dist/lib/cluster/cluster-slots.js:118:19)
at RedisClusterSlots.getClient (/server/node_modules/@redis/client/dist/lib/cluster/cluster-slots.js:110:37)
at Commander._RedisCluster_execute (/server/node_modules/@redis/client/dist/lib/cluster/index.js:217:79)
at Commander.sendCommand (/server/node_modules/@redis/client/dist/lib/cluster/index.js:129:98)
at Commander.commandsExecutor (/server/node_modules/@redis/client/dist/lib/cluster/index.js:126:75)
at BaseClass.<computed> [as get] (/server/node_modules/@redis/client/dist/lib/commander.js:8:29)
at cacheItem (/server/node_modules/xxx:46:34)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async HttpClient.xxx (/server/node_modules/xxx:193:29)
at async Promise.all (index 1)
at async prefetchTask (/server/api/controllers/tasks.js:349:5)
at async Promise.all (index 2)
You can see HttpClient (an internal library being asked to make a request. It then calls cacheItem
(an internal module) which then calls redis.get
as per code below to check if there's something in the cache using get
before making the http request.
Code:
We get the client like this (within an async function). It is long-running, we keep using the same instance once created. Note we pass only one url to rootNodes
- the cluster configuration endpoint provided by AWS Elasticache. (I wonder if that is an issue as the docs say to pass several nodes, I struggled to find docs on this).
...
redisClient = redis.createCluster({
// Assumes we are using AWS Elasticache cluster configuration endpoint
// or similar.
rootNodes: [{ url: config.url }],
defaults: {
// IMPORTANT: Simply not specifying `socket` here seems to
// cause the client to hang regardless of what is in
// `socket`. An empty object suffices to make this go away.
// It's mentioned here:
// https://github.com/redis/node-redis/issues/1656#issuecomment-1212691760
socket: {
// If this is too small, we might get `Error: All the root nodes are unavailable`.
connectTimeout: 5000,
tls: true,
},
},
});
redisClient.on('error', error =>
console.error(
`getRedisClient: error occurred for ${config.url}`,
error,
),
);
// Wait for it to connect to avoid any errors.
await redisClient.connect();
return redisClient;
...
Error is triggered in code like this using the above redisClient
:
const redis = await getRedisClient();
try {
cached = await redis.get(
commandOptions({ returnBuffers: true }),
key,
);
} catch (err) {
... log the error here ...
Node.js Version
18.19.1
Redis Server Version
6.2.6
Node Redis Version
4.6.13
Platform
Linux
Logs
No response