go-redis/redis · error
redis: Watch requires at least one key
Error message
redis: Watch requires at least one key
What it means
Returned by Ring.Watch when the keys slice is empty. A Ring transaction must lock keys on a single shard, so at least one key is required; calling Watch with no keys is a programmer error and is rejected before any shard lookup.
Source
Thrown at ring.go:965
if err = hook(ctx, cmds); err != nil {
errs <- err
}
}(hash, cmds)
}
wg.Wait()
close(errs)
if err := <-errs; err != nil {
return err
}
return cmdsFirstErr(cmds)
}
func (c *Ring) Watch(ctx context.Context, fn func(*Tx) error, keys ...string) error {
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")
}View on GitHub (pinned to 36d97525cd)
Solutions
- Guard the Watch call site: only invoke Watch when len(keys) > 0.
- If an empty key set is legitimately possible in your flow, handle it without a transaction (e.g. skip or use a non-transactional path).
- Audit call sites that build the keys slice to ensure they never produce an empty result.
Example fix
// before
err := ring.Watch(ctx, fn) // no keys -> error
// after
if len(keys) == 0 {
return errors.New("cannot run transaction without keys")
}
err := ring.Watch(ctx, fn, keys...) Defensive patterns
Strategy: validation
Validate before calling
if len(keys) == 0 {
return errors.New("Ring.Watch requires at least one key")
}
return ring.Watch(ctx, fn, keys...) Try / catch
if err := ring.Watch(ctx, fn, keys...); err != nil {
if strings.Contains(err.Error(), "requires at least one key") {
// programmer error: fix the call site
}
} Prevention
- Never call Watch with a variadic slice that may be empty without a length check.
- Add a lint/test asserting Watch call sites always pass >= 1 key.
- Centralize transaction construction in a helper that enforces the invariant.
When it happens
Trigger: Calling ring.Watch(ctx, fn) with no key arguments, or passing a keys slice that resolves to length zero (e.g. unpacking an empty slice via keys...).
Common situations: Dynamic key list computed at runtime that happened to be empty; refactoring that dropped the key argument; calling Watch with a pre-sliced variadic that was filtered down to nothing.
Related errors
- redis: Watch requires at least one shard
- redis: please enter the command to be executed
- redis: AutoPipeline is not supported by Ring
- too many arguments
- redis: GROUPBY is not allowed when multiple aggregators are
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/833ce8642c4824db.json.
Report an issue: GitHub.