Skip to content

Cannot read properties of undefined (reading 'replicas') [calling "get"]Β #2704

Open
@danielbush

Description

@danielbush

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions