redis/go-redis · error
redis: Watch requires at least one shard
Error message
redis: Watch requires at least one shard
What it means
After filtering out empty strings, Ring.Watch found no shard for any of the given keys. This happens when every key maps to no shard (e.g. all keys are empty strings, or no shards have been set on the Ring) — the transaction cannot be executed anywhere.
Source
Thrown at ring.go:1006
if len(keys) == 0 {
return fmt.Errorf("redis: Watch requires at least one key")
}
var shards []*ringShard
for _, key := range keys {
if key != "" {
shard, err := c.sharding.GetByKey(key)
if err != nil {
return err
}
shards = append(shards, shard)
}
}
if len(shards) == 0 {
return fmt.Errorf("redis: Watch requires at least one shard")
}
if len(shards) > 1 {
for _, shard := range shards[1:] {
if shard.Client != shards[0].Client {
err := fmt.Errorf("redis: Watch requires all keys to be in the same shard")
return err
}
}
}
return shards[0].Client.Watch(ctx, fn, keys...)
}
// Close closes the ring client, releasing any open resources.
//
// It is rare to Close a Ring, as the Ring is meant to be long-lived
// and shared between many goroutines.View on GitHub (pinned to c5cad058c7)
Solutions
- Verify the Ring has shards: call ring.Set(...) / AddShard before Watch
- Validate that keys are non-empty strings before invoking Watch
- Inspect key-to-shard mapping; if using a custom hash function, confirm keys hash to a configured shard
Example fix
// before
ring := NewRing(NewRingOptions()) // no shards added
ring.Watch(ctx, fn, "k1")
// after
ring := NewRing(NewRingOptions())
ring.Set(ctx, &RingShard{Client: redis.NewClient(&redis.Options{Addr: ":6379"}), Weight: 1})
ring.Watch(ctx, fn, "k1") Defensive patterns
Strategy: validation
Validate before calling
if ring == nil || len(ring.shards) == 0 { /* check via ring.Get/HasShard API */ }
for _, k := range keys {
if k == "" { return errors.New("Watch: empty key") }
} Try / catch
if err := ring.Watch(ctx, fn, keys...); err != nil {
if strings.Contains(err.Error(), "requires at least one shard") {
return fmt.Errorf("ring misconfigured: %w", err)
}
return err
} Prevention
- Call ring.Set/AddShard before any Watch usage
- Sanitize keys: skip or reject empty strings early
- Add a startup health check that pings every Ring shard
When it happens
Trigger: Calling ringClient.Watch(ctx, fn, keys...) where all keys are "" (skipped by the non-empty check) or the Ring has no shards configured (Set/AddShard never called or cleared), at ring.go:1006.
Common situations: Constructing a Ring programmatically and forgetting ring.Set/AddShard before use; keys derived from data where all values are empty strings; a Ring whose shard list was wiped by reconfiguration.
Related errors
- redis: Watch requires at least one key
- redis: Watch requires all keys to be in the same shard
- both LibName and LibVer cannot be set at the same time
- at least one of LibName and LibVer should be set
- csc: a different "invalidate" push handler is already regist
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/a12917f424b62576.
Report an issue: GitHub.