go-redis/redis · critical
redis: no sentinels configured
Error message
redis: no sentinels configured
What it means
Returned by the sentinel failover client when there are no sentinel addresses configured (c.sentinelAddrs is empty) after the initial sentinel lookup path fails to find a master. The failover client needs at least one Sentinel to discover the current master; with none configured it cannot proceed.
Source
Thrown at sentinel.go:1000
if c.sentinel != nil {
addr, err := c.getMasterAddr(ctx, c.sentinel)
if err != nil {
_ = c.closeSentinel()
if isContextError(ctx.Err()) {
return "", err
}
// Continue on other errors
internal.Logger.Printf(ctx, "sentinel: GetMasterAddrByName name=%q failed: %s",
c.opt.MasterName, err)
} else {
return addr, nil
}
}
// short circuit if no sentinels configured
if len(c.sentinelAddrs) == 0 {
return "", errors.New("redis: no sentinels configured")
}
var (
masterAddr string
wg sync.WaitGroup
once sync.Once
errCh = make(chan error, len(c.sentinelAddrs))
)
ctx, cancel := context.WithCancel(ctx)
defer cancel()
for i, sentinelAddr := range c.sentinelAddrs {
wg.Add(1)
go func(i int, addr string) {
defer wg.Done()
sentinelCli := NewSentinelClient(c.opt.sentinelOptions(addr))
addrVal, err := sentinelCli.GetMasterAddrByName(ctx, c.opt.MasterName).Result()View on GitHub (pinned to 36d97525cd)
Solutions
- Provide at least one sentinel address in FailoverOptions.SentinelAddrs (one per Sentinel instance).
- Validate that the config source (env var, file) actually populated SentinelAddrs before constructing the client.
- Add a startup assertion: if len(opts.SentinelAddrs) == 0 { return error }.
Example fix
// before — MasterName set but no sentinels
client := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "mymaster",
// SentinelAddrs missing/empty
})
// client.Get(ctx, "k").Err() => redis: no sentinels configured
// after
client := redis.NewFailoverClient(&redis.FailoverOptions{
MasterName: "mymaster",
SentinelAddrs: []string{"sentinel-1:26379", "sentinel-2:26379"},
}) Defensive patterns
Strategy: validation
Validate before calling
func validateFailoverOpts(o *redis.FailoverOptions) error {
if o.MasterName == "" {
return errors.New("MasterName is required")
}
if len(o.SentinelAddrs) == 0 {
return errors.New("SentinelAddrs is empty; provide at least one sentinel host:port")
}
return nil
} Prevention
- Assert len(FailoverOptions.SentinelAddrs) > 0 at startup.
- Load-test config sources to ensure SentinelAddrs is populated in all environments.
- Include MasterName and at least 2-3 Sentinel addresses for redundancy.
When it happens
Trigger: Creating a FailoverClient with an empty SentinelAddrs slice and no MasterName-driven discovery. SentinelAddrs was set only on Options but the failover options path didn't receive them. A misconfigured SentinelOptions where the addrs slice is nil/empty.
Common situations: Configuring redis.NewFailoverClient with MasterName but forgetting SentinelAddrs. Environment/config loading that returns an empty address list (env var not set, config file parse error). Copy-paste errors omitting the SentinelAddrs field.
Related errors
- redis: all sentinels specified in configuration are unreacha
- redis: all sentinels specified in configuration are unreacha
- redis: NewSentinelClient nil options
- redis: NewFailoverClusterClient nil options
- redis: connection pool exhausted
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/e13247cffa8b36bb.json.
Report an issue: GitHub.