redis/node-redis · error · Error

Could not find shard

Error message

Could not find shard

What it means

Thrown inside #handleSmigrated (the cluster slot-migration event handler) when a destination node exists in nodeByAddress but its shard cannot be located in the slots array by host+port. This indicates an internal topology-bookkeeping inconsistency during a live slot migration (SMIGRATED event), where the destination master is known but not yet mapped in the slot table.

Solutions

  1. Ensure topologyRefreshOnReconnectionAttempt and maxCommandRedirections allow the client to recover via normal MOVED/ASK redirection rather than relying solely on SMIGRATED events.
  2. Upgrade to the latest node-redis patch release, as this is an internal consistency path that receives fixes.
  3. If reproducible, capture the SMIGRATED event payload and cluster topology (CLUSTER SLOTS) and report it as a bug with the dbgMaintenance logs.
  4. As a workaround, call cluster.disconnect() then cluster.connect() to force a clean full rediscovery after the error.
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

function isShardNotFound(e: unknown): boolean {
  return e instanceof Error && e.message === 'Could not find shard';
}

Try / catch

try {
  await cluster.set('k', 'v');
} catch (e) {
  if (e instanceof Error && e.message === 'Could not find shard') {
    // internal topology inconsistency during migration; force rediscovery
    await cluster.disconnect();
    await cluster.connect();
  } else throw e;
}

Prevention

When it happens

Trigger: A SMIGRATED cluster event arrives naming a destination node that is in nodeByAddress but whose Shard was not yet inserted into the slots array (concurrent topology refresh, partial migration state, or a race between discovery and migration events). This is an internal/library-level consistency failure, not typically user-triggered.

Common situations: Active cluster resharding/rebalancing while the client is also refreshing topology; rapid sequential migrations where an intermediate event references a node mid-update; a bug in slot-table maintenance during concurrent #discover and #handleSmigrated; cluster version producing migration events the client does not fully reconcile.

Related errors


AI-assisted analysis of redis/node-redis@90fd0652bc (2026-08-11). Data as JSON: /api/errors/7bb34c8116902ac3. Report an issue: GitHub.

Appendix: source

Thrown at packages/client/lib/cluster/cluster-slots.ts:491

            const promises: Promise<unknown>[] = [];
            destMasterNode = this.#initiateSlotNode({ host: host, port: port, id: `smigrated-${host}:${port}` }, false, true, new Set(), promises);
            await Promise.all([...promises, this.#initiateShardedPubSubClient(destMasterNode)]);
            // Pause new destination until migration is complete
            destMasterNode.client?._pause();
            destMasterNode.pubSub?.client._pause();
            // In case destination node didnt exist, this means Shard didnt exist as well, so creating a new Shard is completely fine
            destShard = {
              master: destMasterNode
            };
          } else {
            // DEBUG: Log all master hosts/ports in slots array to diagnose mismatch
            const allMasters = [...new Set(this.slots)].map(s => `${s.master.host}:${s.master.port}`);
            dbgMaintenance(`[CSlots]: Searching for shard with host=${host}, port=${port}. Available masters in slots: ${allMasters.join(', ')}`);
            // In case destination node existed, this means there was a Shard already, so its best if we can find it.
            const existingShard = this.slots.find(shard => shard.master.host === host && shard.master.port === port);
            if (!existingShard) {
              dbgMaintenance("Could not find shard");
              throw new Error('Could not find shard');
            }
            destShard = existingShard;
            // Pause existing destination during command transfer
            destMasterNode.client?._pause();
            destMasterNode.pubSub?.client._pause();
          }

          // Track last destination for slotless commands later
          lastDestNode = destMasterNode;

          // 3. Convert slots to Set and update shard mappings
          const destinationSlots = new Set<number>();
          for (const slot of slots) {
            if (typeof slot === 'number') {
              this.slots[slot] = destShard;
              destinationSlots.add(slot);
              allMovingSlots.add(slot);
            } else {

View on GitHub (pinned to 90fd0652bc)