How to fix ERR crossed slot boundary in Redis

RedisINTERMEDIATEHIGHUpdated Dec 25, 2025· 223 views

The "ERR crossed slot boundary" (also displayed as "CROSSSLOT Keys in request don't hash to the same slot") error occurs in Redis Cluster when a multi-key command attempts to operate on keys that hash to different hash slots. Redis Cluster divides data across 16,384 slots, and multi-key operations like MGET, MSET, and Lua scripts require all keys to reside in the same slot. Fix by using hash tags to ensure keys hash to the same slot, or by executing separate commands on each slot.

Quick fix

Fixes ERR crossed slot boundary

redis-cli -c CLUSTER KEYSLOT key1
redis-cli -c CLUSTER KEYSLOT key2
redis-cli -c CLUSTER KEYSLOT key3
  1. Identify which keys are in different slots
  2. Use hash tags to force keys to the same slot
  3. Refactor multi-key operations into slot-specific commands
  4. Fix Lua scripts to operate on keys in the same slot
redis — error
redis-cli -c CLUSTER KEYSLOT key1
redis-cli -c CLUSTER KEYSLOT key2
redis-cli -c CLUSTER KEYSLOT key3
ERR crossed slot boundary

What this error means

Redis Cluster uses hash slots to distribute data across multiple nodes. When you execute a multi-key command (MGET, MSET, DEL, etc.), all keys involved must hash to the same slot so the command can be executed atomically on a single node. If keys hash to different slots, Redis rejects the command with "ERR crossed slot boundary" or "CROSSSLOT Keys in request don't hash to the same slot". This restriction exists because Redis Cluster does not support cross-slot transactions or distributed operations. The error acts as a safety mechanism to prevent undefined behavior when operations would need to coordinate across multiple nodes.

Typical symptoms

  • MGET, MSET, or other multi-key commands fail with "ERR crossed slot boundary"
  • Lua scripts using EVAL fail when accessing keys on different slots
  • Operations like SUNION, SINTER, or ZUNIONSTORE fail across slots
  • Transaction errors when using keys that hash to different slots
  • Application logic that worked in standalone Redis fails in cluster mode
  • DEL commands fail when targeting keys on different slots

Common causes

  1. Using multi-key commands (MGET, MSET, DEL, etc.) with keys that have different hash values (most common)
  2. Lua scripts in EVAL/EVALSHA access multiple keys without ensuring they hash to the same slot
  3. Migrating from standalone Redis to cluster mode without updating key naming conventions
  4. Using set operations (SUNION, SINTER, ZINTERSTORE) on keys that don't share the same slot
  5. Not using hash tags to force keys to the same slot
  6. Client library misconfiguration that doesn't handle multi-slot commands properly

How to fix "ERR crossed slot boundary"

1Identify which keys are in different slots

Use the CLUSTER KEYSLOT command to determine which slot each key hashes to. This will show you which keys are causing the crossed slot boundary error.

bash
redis-cli -c CLUSTER KEYSLOT key1
redis-cli -c CLUSTER KEYSLOT key2
redis-cli -c CLUSTER KEYSLOT key3

Each command returns an integer representing the slot (0-16383). If the slots differ, that's why your multi-key command is failing.

Example:

bash
> CLUSTER KEYSLOT user:1001:name
(integer) 5598
> CLUSTER KEYSLOT user:1001:email
(integer) 7967

In this case, the two keys hash to different slots (5598 vs 7967), so commands like MGET user:1001:name user:1001:email will fail.

2Use hash tags to force keys to the same slot

Redis Cluster uses hash tags (substrings in curly braces) to allow multiple keys to map to the same slot. Only the substring within {} is used for slot calculation.

bash
# WRONG - keys hash to different slots
MGET user:1001:name user:1001:email

# CORRECT - use hash tags so all keys hash to the same slot
MGET user:{1001}:name user:{1001}:email

With hash tags, the slot is calculated based only on "1001", so both keys will hash to the same slot. This allows the MGET command to succeed.

Examples:

bash
# All these keys hash to the same slot (based on "user123")
SET user:{user123}:name "Alice"
SET user:{user123}:email "alice@example.com"
SET user:{user123}:age 30
MGET user:{user123}:name user:{user123}:email user:{user123}:age

Guidelines for hash tags:
- Wrap the identifying portion of the key in {curly braces}
- Only the portion inside {} is hashed
- Everything outside {} is ignored for slot calculation
- Keep the identifying portion short and consistent

3Refactor multi-key operations into slot-specific commands

If hash tags aren't feasible for your schema, execute separate commands for each slot. This requires knowing which slot each key belongs to.

javascript
// WRONG - fails with CROSSSLOT error
const values = await redis.mget(['key1', 'key2', 'key3']);

// CORRECT - execute commands per slot
async function multiGetBySlot(keys) {
  const keysBySlot = {};

  // Group keys by their slot
  for (const key of keys) {
    const slot = await redis.clusterKeyslot(key);
    if (!keysBySlot[slot]) keysBySlot[slot] = [];
    keysBySlot[slot].push(key);
  }

  // Execute MGET for each slot separately
  const results = [];
  for (const slot in keysBySlot) {
    const slotKeys = keysBySlot[slot];
    const slotResults = await redis.mget(slotKeys);
    results.push(...slotResults);
  }

  return results;
}

This approach works but is more complex and slower than keeping keys in the same slot.

4Fix Lua scripts to operate on keys in the same slot

Lua scripts used with EVAL/EVALSHA must declare all keys they'll access. If keys are in different slots, the command will fail.

bash
# WRONG - script accesses keys in different slots
EVAL "return {redis.call('GET', KEYS[1]), redis.call('GET', KEYS[2])}" 0 user:name user:email

# CORRECT - use hash tags to ensure keys are in same slot
EVAL "return {redis.call('GET', KEYS[1]), redis.call('GET', KEYS[2])}" 2 user:{123}:name user:{123}:email

The key insight: all keys declared in KEYS[...] must hash to the same slot. Use hash tags consistently throughout your Lua scripts.

Example with proper hash tags:

lua
-- Lua script with hash tags
local name = redis.call('GET', KEYS[1])
local email = redis.call('GET', KEYS[2])
local age = redis.call('GET', KEYS[3])
return {name, email, age}

Call it with:

bash
EVAL "..." 3 user:{1001}:name user:{1001}:email user:{1001}:age
5Verify your client library supports cluster mode properly

Some Redis client libraries provide automatic handling for cross-slot commands. Check your client's documentation.

For JavaScript (ioredis):

javascript
const redis = require('ioredis');
const cluster = new redis.Cluster([
  { host: 'localhost', port: 6379 },
]);

// ioredis with enableAutoPipelining can handle this
const values = await cluster.mget(['key1', 'key2', 'key3']);

For Go (rueidis):

go
// rueidis v0.0.94+ has an MGet helper for cross-slot commands
results, err := c.Do(ctx, c.B().Mget().Keys(key1, key2, key3).Build()).AsStrSlice()

For Java (Lettuce):

java
// Lettuce automatically decomposes multi-key commands across slots
List<String> values = commands.mget(key1, key2, key3);

If your client library supports it, enable automatic cross-slot handling. Otherwise, use hash tags or manual slot management.

6Check if you should use Redis Enterprise instead

If your use case genuinely requires arbitrary multi-key operations across slots without hash tags, consider these options:

Redis Enterprise supports these multi-key commands across slots:
- MGET
- MSET
- DEL
- EXISTS
- UNLINK
- TOUCH

Switch to Redis Enterprise if you have many operations that require cross-slot access and cannot be redesigned with hash tags.

Standalone Redis (non-cluster) has no slot restrictions:
- If you don't need cluster mode's scalability, use standalone Redis for simpler operations
- Cluster mode is for horizontal scaling when you need it

Evaluate your requirements:
- Do you need to scale across multiple nodes? → Use Cluster with hash tags
- Do you need arbitrary multi-key operations? → Use Enterprise or Standalone
- Can you redesign your schema with hash tags? → Use standard Cluster mode (cost-effective)

Advanced notes

Hash Slot Distribution: Redis Cluster automatically divides the 16,384 hash slots across nodes. When you add or remove nodes, slots are rebalanced. The slot for a key is calculated as CRC16(key) mod 16384, where CRC16 uses only the portion in curly braces if hash tags are present.

Hash Tag Limitations: Hash tags only affect slot calculation. The portion outside {} is still part of the key name, so {user123}:name and {user123}:email are different keys with the same slot. You can use multiple levels of nesting, but only the innermost {curly} portion is hashed.

Performance Implications: Using hash tags keeps related keys on the same node, which can create hotspots if one user or entity has many keys. Monitor slot distribution and consider resharding if one slot becomes too hot.

Cluster Resharding: During resharding, keys move between nodes. The CLUSTER KEYSLOT command will still return the correct slot after resharding; it's based on the key itself, not the node location.

Redis OSS vs Enterprise: Open source Redis Cluster is strict about slot boundaries. Redis Enterprise adds a "Conflict-free Replicated Data Type" (CRDT) mode that allows some cross-slot operations. Check your deployment's capabilities.

Debugging Tools: Use redis-cli with the -c (cluster) flag to connect to any node in the cluster. It will redirect you automatically. Use CLUSTER INFO to see overall cluster state and CLUSTER NODES to see slot distribution across nodes.

Frequently asked questions

What does "ERR crossed slot boundary" mean?
Redis Cluster uses hash slots to distribute data across multiple nodes. ), all keys involved must hash to the same slot so the command can be executed atomically on a single node. If keys hash to different slots, Redis rejects the command with "ERR crossed slot boundary" or "CROSSSLOT Keys in request don't hash to the same slot".
How do I fix "ERR crossed slot boundary"?
The "ERR crossed slot boundary" (also displayed as "CROSSSLOT Keys in request don't hash to the same slot") error occurs in Redis Cluster when a multi-key command attempts to operate on keys that hash to different hash slots. Redis Cluster divides data across 16,384 slots, and multi-key operations like MGET, MSET, and Lua scripts require all keys to reside in the same slot. Fix by using hash tags to ensure keys hash to the same slot, or by executing separate commands on each slot.
What causes "ERR crossed slot boundary"?
Using multi-key commands (MGET, MSET, DEL, etc.) with keys that have different hash values (most common) Lua scripts in EVAL/EVALSHA access multiple keys without ensuring they hash to the same slot Migrating from standalone Redis to cluster mode without updating key naming conventions
Is the "ERR crossed slot boundary" error serious?
Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.

Official resources & further reading