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

  1. Verify the Ring has shards: call ring.Set(...) / AddShard before Watch
  2. Validate that keys are non-empty strings before invoking Watch
  3. 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

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


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/a12917f424b62576. Report an issue: GitHub.