{"record":{"id":"7bb34c8116902ac3","repo":"redis/node-redis","slug":"could-not-find-shard","errorCode":null,"errorMessage":"Could not find shard","messagePattern":"Could not find shard","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/client/lib/cluster/cluster-slots.ts","lineNumber":491,"sourceCode":"            const promises: Promise<unknown>[] = [];\n            destMasterNode = this.#initiateSlotNode({ host: host, port: port, id: `smigrated-${host}:${port}` }, false, true, new Set(), promises);\n            await Promise.all([...promises, this.#initiateShardedPubSubClient(destMasterNode)]);\n            // Pause new destination until migration is complete\n            destMasterNode.client?._pause();\n            destMasterNode.pubSub?.client._pause();\n            // In case destination node didnt exist, this means Shard didnt exist as well, so creating a new Shard is completely fine\n            destShard = {\n              master: destMasterNode\n            };\n          } else {\n            // DEBUG: Log all master hosts/ports in slots array to diagnose mismatch\n            const allMasters = [...new Set(this.slots)].map(s => `${s.master.host}:${s.master.port}`);\n            dbgMaintenance(`[CSlots]: Searching for shard with host=${host}, port=${port}. Available masters in slots: ${allMasters.join(', ')}`);\n            // In case destination node existed, this means there was a Shard already, so its best if we can find it.\n            const existingShard = this.slots.find(shard => shard.master.host === host && shard.master.port === port);\n            if (!existingShard) {\n              dbgMaintenance(\"Could not find shard\");\n              throw new Error('Could not find shard');\n            }\n            destShard = existingShard;\n            // Pause existing destination during command transfer\n            destMasterNode.client?._pause();\n            destMasterNode.pubSub?.client._pause();\n          }\n\n          // Track last destination for slotless commands later\n          lastDestNode = destMasterNode;\n\n          // 3. Convert slots to Set and update shard mappings\n          const destinationSlots = new Set<number>();\n          for (const slot of slots) {\n            if (typeof slot === 'number') {\n              this.slots[slot] = destShard;\n              destinationSlots.add(slot);\n              allMovingSlots.add(slot);\n            } else {","sourceCodeStart":473,"sourceCodeEnd":509,"githubUrl":"https://github.com/redis/node-redis/blob/90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58/packages/client/lib/cluster/cluster-slots.ts#L473-L509","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"null","typeGuard":"function isShardNotFound(e: unknown): boolean {\n  return e instanceof Error && e.message === 'Could not find shard';\n}","tryCatchPattern":"try {\n  await cluster.set('k', 'v');\n} catch (e) {\n  if (e instanceof Error && e.message === 'Could not find shard') {\n    // internal topology inconsistency during migration; force rediscovery\n    await cluster.disconnect();\n    await cluster.connect();\n  } else throw e;\n}","preventionTips":["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."],"tags":["cluster","topology","migration","internal"],"backgroundTag":null,"analyzedSha":"90fd0652bc3f2a0a1b2f79fa9096b02a86b0ac58","analyzedAt":"2026-08-11T15:37:21.243Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}