redis/node-redis · error · MaxCommandRedirectionsError

Too many Cluster redirections

Error message

Too many Cluster redirections

What it means

Thrown as MaxCommandRedirectionsError when a single command in the core _execute transport loop receives more MOVED or ASK redirections than the configured limit (default 16). Each redirect means the slot moved to a different node mid-flight; exceeding the ceiling indicates the cluster topology is in a state where redirects chain faster than the client can re-resolve.

Source

Thrown at packages/client/lib/cluster/index.ts:733

          myFn = fn;

          if (!(err instanceof Error)) {
            throw err;
          }

          const isRedirect = err.message.startsWith('ASK') || err.message.startsWith('MOVED');

          if (++i > maxCommandRedirections) {
            publish(CHANNELS.ERROR, () => ({
              error: err,
              origin: 'cluster',
              internal: false,
              clientId: client._clientId,
              retryCount: i,
            }));

            if (isRedirect) {
              throw new MaxCommandRedirectionsError(err);
            }
            throw err;
          }

          if (err.message.startsWith('ASK')) {
            publish(CHANNELS.ERROR, () => ({
              error: err,
              origin: 'cluster',
              internal: true,
              clientId: client._clientId,
              retryCount: i,
            }));
            const address = err.message.substring(err.message.lastIndexOf(' ') + 1);
            let redirectTo = await this._slots.getMasterByAddress(address);
            if (!redirectTo) {
              await this._slots.rediscover(client);
              redirectTo = await this._slots.getMasterByAddress(address);
            }

View on GitHub (pinned to 90fd0652bc)

Solutions

  1. Increase `maxCommandRedirections` in the cluster options (default 16) to tolerate more redirect hops
  2. Wait for resharding or failover to complete before retrying
  3. Run CLUSTER NODES / CLUSTER SLOTS on each node to check for topology inconsistencies
  4. If using a proxy, verify it passes MOVED/ASK responses through unchanged

Example fix

// before — default limit of 16 redirects
const cluster = createCluster({ rootNodes: [...] });

// after — raise the ceiling during heavy resharding
const cluster = createCluster({
  rootNodes: [...],
  maxCommandRedirections: 32
});
Defensive patterns

Strategy: retry

Type guard

import { MaxCommandRedirectionsError } from '@redis/client/dist/lib/errors';

function isMaxRedirections(err: unknown): err is MaxCommandRedirectionsError {
  return err instanceof MaxCommandRedirectionsError;
}

Try / catch

async function withRedirectRetry<T>(fn: () => Promise<T>, maxRetries = 2): Promise<T> {
  try {
    return await fn();
  } catch (err) {
    if (maxRetries > 0 && err instanceof MaxCommandRedirectionsError) {
      await new Promise(r => setTimeout(r, 1000));
      return withRedirectRetry(fn, maxRetries - 1);
    }
    throw err;
  }
}

Prevention

When it happens

Trigger: Active slot resharding where MOVED responses form a loop (node A redirects to B, B redirects back to A); stale slots table that never updates despite rediscovery calls; ASK redirects during failover where the target node keeps rejecting with further ASKs.

Common situations: Heavy resharding in progress; cluster topology split-brain where nodes disagree on slot ownership; proxy or load balancer that mangles MOVED/ASK responses; maxCommandRedirections set too low for a turbulent cluster.

Related errors


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