redis/node-redis · error · Error

No slots to migrate

Error message

No slots to migrate

What it means

Internal invariant guard inside buildSMigratedNotification — the RESP encoder for the SMIGRATED push notification. It rejects an empty movedSlotsByDestination array because an SMIGRATED notification carrying zero slot-move entries is meaningless. The sole in-repo caller (triggerMigrate) always passes exactly one entry, so this is a defensive check for future callers or direct use of the helper.

Source

Thrown at packages/test-utils/lib/fault-injector/proxied-fault-injector-cluster.ts:183

  return {
    id,
    host,
    port: Number(port),
    proxyPort: Number(proxyPort),
  };
};

const buildSMigratedNotification = (
  movedSlotsByDestination: Array<{
    targetNode: { host: string; port: number };
    slotRanges: string; // e.g., "0-5460" or "0-100,200-300,500"
  }>,
  seqId: number = 1,
  encoding: "base64" | "raw" = "base64"
): string => {
  if (movedSlotsByDestination.length === 0) {
    throw new Error("No slots to migrate");
  }

  const entries = movedSlotsByDestination.map(({ targetNode, slotRanges }) => {
    const hostPort = `${targetNode.host}:${targetNode.port}`;
    return `*2\r\n+${hostPort}\r\n+${slotRanges}\r\n`;
  });

  const response = `>3\r\n+SMIGRATED\r\n:${seqId}\r\n*${
    movedSlotsByDestination.length
  }\r\n${entries.join("")}`;

  return encoding === "raw"
    ? response
    : Buffer.from(response).toString(encoding);
};

const buildClusterSlotsResponse = (
  nodes: ProxyNode[],

View on GitHub (pinned to 90fd0652bc)

Solutions

  1. Pass at least one { targetNode, slotRanges } entry to buildSMigratedNotification.
  2. If entries are computed dynamically, guard upstream and skip emitting the SMIGRATED notification entirely when there is nothing to migrate instead of calling the helper with [].

Example fix

// before
const entries = pickEntries(); // may be []
const notif = buildSMigratedNotification(entries);

// after
const entries = pickEntries();
if (entries.length === 0) return { status: 'success', error: null, output: 'Nothing to migrate' };
const notif = buildSMigratedNotification(entries);
Defensive patterns

Strategy: validation

Validate before calling

function hasMigratedEntries(entries: Array<{ targetNode: { host: string; port: number }; slotRanges: string }>): boolean {
  return entries.length > 0 && entries.every(e => e.slotRanges.length > 0);
}
// only call buildSMigratedNotification when hasMigratedEntries(entries) is true

Type guard

const isNonEmptyEntries = (e: unknown): e is Array<{ targetNode: { host: string; port: number }; slotRanges: string }> =>
  Array.isArray(e) && e.length > 0;

Prevention

When it happens

Trigger: Calling buildSMigratedNotification([]) directly, or a future caller that computes the destination/slot list dynamically and passes an empty array because no slots were selected or no destination node was found.

Common situations: Refactoring triggerMigrate to build the entries list conditionally (e.g., filtering nodes) such that it can become empty; a new fault-injection scenario reusing the helper without guaranteeing at least one entry.

Related errors


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