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
- Ensure topologyRefreshOnReconnectionAttempt and maxCommandRedirections allow the client to recover via normal MOVED/ASK redirection rather than relying solely on SMIGRATED events.
- Upgrade to the latest node-redis patch release, as this is an internal consistency path that receives fixes.
- If reproducible, capture the SMIGRATED event payload and cluster topology (CLUSTER SLOTS) and report it as a bug with the dbgMaintenance logs.
- 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
- Keep the client on the latest patch release for topology/migration fixes.
- Ensure MOVED/ASK redirection and topology refresh are enabled to recover from migration races.
- Report reproducible cases with dbgMaintenance logs and CLUSTER SLOTS output.
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
- [Proxy] No destination node
- Cannot find node
- Cannot split : invalid keystep
- Cannot split : unsupported find_keys type
- No slots to migrate
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)