go-redis/redis · error

redis: all sentinels specified in configuration are unreacha

Error message

redis: all sentinels specified in configuration are unreachable: %w

What it means

Returned (not panicked) by sentinelFailover.masterAddr when every configured Sentinel address failed the GetMasterAddrByName query. Each per-sentinel error is collected and joined into the wrapped cause. An empty masterAddr after the fan-out wait means no Sentinel was reachable or knew the master.

Source

Thrown at sentinel.go:1051

				cancel()
			})

			if sentinelCli != c.sentinel {
				_ = sentinelCli.Close()
			}
		}(i, sentinelAddr)
	}

	wg.Wait()
	close(errCh)
	if masterAddr != "" {
		return masterAddr, nil
	}
	errs := make([]error, 0, len(errCh))
	for err := range errCh {
		errs = append(errs, err)
	}
	return "", fmt.Errorf("redis: all sentinels specified in configuration are unreachable: %w", errors.Join(errs...))
}

func (c *sentinelFailover) replicaAddrs(ctx context.Context, useDisconnected bool) ([]string, error) {
	c.mu.RLock()
	sentinel := c.sentinel
	c.mu.RUnlock()

	if sentinel != nil {
		addrs, err := c.getReplicaAddrs(ctx, sentinel)
		if err != nil {
			if isContextError(ctx.Err()) {
				return nil, err
			}
			// Continue on other errors
			internal.Logger.Printf(ctx, "sentinel: Replicas name=%q failed: %s",
				c.opt.MasterName, err)
		} else if len(addrs) > 0 {
			return addrs, nil

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Verify each Sentinel address in SentinelAddrs is reachable (telnet/curl to port 26379) from the client host.
  2. Confirm MasterName matches the monitor name configured on the Sentinels (sentinel masters).
  3. Check the wrapped error(s) for the specific failure (connection refused, timeout, authentication, i/o).
  4. Add additional/fallback Sentinel addresses and ensure at least one is healthy.
  5. If using TLS or auth, make sure Sentinel credentials/options match the Sentinel deployment.

Example fix

// before
client := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName:   "mymaster",
    SentinelAddrs: []string{":26379"}, // wrong port / unreachable
})

// after
client := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName:   "mymaster",
    SentinelAddrs: []string{"sentinel-0:26379", "sentinel-1:26379", "sentinel-2:26379"},
})
Defensive patterns

Strategy: try-catch

Validate before calling

func pingSentinels(addrs []string, timeout time.Duration) error {
    for _, a := range addrs {
        conn, err := net.DialTimeout("tcp", a, timeout)
        if err != nil {
            continue
        }
        conn.Close()
        return nil
    }
    return fmt.Errorf("no sentinel reachable from %v", addrs)
}

Try / catch

client := redis.NewFailoverClient(opt)
if err := client.Ping(ctx).Err(); err != nil {
    // err may wrap 'all sentinels ... unreachable'; log and retry/backoff
    if strings.Contains(err.Error(), "all sentinels") {
        // retry with backoff or surface to operator
    }
}

Prevention

When it happens

Trigger: Using redis.NewFailoverClient / NewFailoverClusterClient where every address in SentinelAddrs is unreachable, returns an error, or does not know MasterName; also when SentinelAddrs is populated but MasterName is wrong/empty.

Common situations: Network partition or firewall blocking the Sentinel port (26379), wrong MasterName, Sentinel list pointing at stale/decommissioned hosts, Sentinel process down, TLS mismatch, or DNS resolving but connection refused.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/45bdea9f3821d2c7.json. Report an issue: GitHub.