The MOVED error occurs in Redis Cluster when a client connects to the wrong node for a given hash slot. The cluster returns this error with the correct node address, requiring the client to redirect the query or update its topology knowledge.
In Redis Cluster, data is distributed across multiple nodes using hash slots. Each hash slot is owned by a specific node. When a client sends a command to a node, Redis checks if the requested key's hash slot is stored on that node. If the hash slot is located on a different node, Redis responds with a MOVED error that includes the correct node's address and port. This indicates a permanent redirection—the slot has been moved and the client should update its cluster topology information and retry the command against the correct node. Unlike the ASK error (which is temporary during resharding), MOVED means the cluster topology has changed and the client's view of the cluster is outdated.
The simplest solution is to use a Redis client that natively supports cluster mode. Most popular Redis clients (redis-py, node-redis, Lettuce, Jedis) handle MOVED redirects automatically.
For Python (redis-py):
from redis.cluster import RedisCluster
# Cluster-aware client automatically handles redirects
rc = RedisCluster(startup_nodes=[{"host": "localhost", "port": 7000}])
rc.set("mykey", "myvalue")For Node.js (node-redis):
const { createCluster } = require("redis");
const cluster = createCluster({
rootNodes: [
{ host: "localhost", port: 7000 },
],
});
await cluster.connect();
await cluster.set("mykey", "myvalue");Cluster-aware clients automatically:
- Discover all nodes in the cluster
- Map keys to their hash slots
- Route requests to the correct node
- Handle MOVED and ASK redirects transparently
If your client doesn't automatically handle redirects, refresh the cluster topology when you receive a MOVED error.
The client should execute the CLUSTER SHARDS (or deprecated CLUSTER SLOTS) command to get the latest mapping:
redis-cli -c CLUSTER SHARDSThis returns all nodes and their slot ranges. Your client should:
1. Cache this topology
2. Update it whenever a MOVED error is received
3. Use the new mapping for future commands
Many clients support this with a configuration option like auto_refresh_on_moved or similar.
If you're testing with redis-benchmark against a cluster, use the -c flag to enable cluster mode:
redis-benchmark -h 127.0.0.1 -p 7000 -c -q -n 100000The -c flag makes redis-benchmark cluster-aware, so it can follow MOVED redirects and correctly distribute keys across nodes.
Without -c, redis-benchmark sends all commands to a single node, triggering MOVED errors for keys that belong to other nodes.
Check that your Redis Cluster is healthy and all slots are assigned:
redis-cli -c CLUSTER INFO
redis-cli -c CLUSTER NODESLook for:
- "cluster_state:ok" (not "fail")
- All 16384 slots assigned to nodes
- No nodes in "migrating" or "importing" state (unless actively resharding)
If you see "cluster_slots_fail" or unassigned slots, the cluster topology is broken. Run:
redis-cli --cluster fix <any-node>:6379to attempt automatic repair.
If implementing a custom Redis client, handle MOVED errors by parsing the response and retrying:
// Pseudo-code
function executeCommand(command, key) {
const slot = crc16(key) % 16384;
const node = topologyMap[slot];
try {
return send(node, command);
} catch (err) {
if (err.message.includes("MOVED")) {
// Parse: "MOVED <slot> <host>:<port>"
const [_, newSlot, hostPort] = err.message.split(" ");
const [host, port] = hostPort.split(":");
// Update topology
topologyMap[newSlot] = { host, port };
// Retry command against new node
return send({ host, port }, command);
}
throw err;
}
}Additionally, periodically refresh the cluster topology to proactively catch topology changes.
Understanding MOVED vs ASK:
- MOVED: Permanent redirection. The hash slot has been moved to a different node. Update your cluster topology and route future queries to the new node.
- ASK: Temporary redirection. A slot is being migrated and this key is in the target node. Send only the next query to the specified node, then resume normal routing.
Cluster topology refresh strategies:
- Proactive: Query CLUSTER SHARDS periodically (e.g., every 60 seconds)
- Reactive: Refresh only when MOVED errors occur
- Hybrid: Short periodic refresh + immediate refresh on MOVED
For production systems, use a cluster-aware client library rather than implementing redirection logic yourself. Libraries like Lettuce (Java), redis-py (Python), and ioredis (Node.js) handle all the complexity transparently.
If seeing frequent MOVED errors after no topology changes, your client's connection pool may be reusing stale connections. Ensure your client creates fresh connections to newly discovered nodes.
ERR Unbalanced XREAD list of streams
How to fix "ERR Unbalanced XREAD list" in Redis
ERR syntax error
How to fix "ERR syntax error" in Redis
ConnectionError: Error while reading from socket
ConnectionError: Error while reading from socket in redis-py
ERR unknown command
How to fix ERR unknown command in Redis
Command timed out
How to fix 'Command timed out' in ioredis