redis/go-redis · error

to route commands by latency, use NewFailoverClusterClient

Error message

to route commands by latency, use NewFailoverClusterClient

What it means

NewFailoverClient rejects FailoverOptions.RouteByLatency=true because read-by-latency routing is only implemented by the cluster client. The sentinel failover client has no latency-based replica routing, so the constructor panics to point the developer at the correct constructor.

Source

Thrown at sentinel.go:549

	// any parameters left?
	if r := q.remaining(); len(r) > 0 {
		return nil, fmt.Errorf("redis: unexpected option: %s", strings.Join(r, ", "))
	}

	return o, nil
}

// NewFailoverClient returns a Redis client that uses Redis Sentinel
// for automatic failover. It's safe for concurrent use by multiple
// goroutines.
// Passing nil FailoverOptions will cause a panic.
func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
	if failoverOpt == nil {
		panic("redis: NewFailoverClient nil options")
	}

	if failoverOpt.RouteByLatency {
		panic("to route commands by latency, use NewFailoverClusterClient")
	}
	if failoverOpt.RouteRandomly {
		panic("to route commands randomly, use NewFailoverClusterClient")
	}

	sentinelAddrs := make([]string, len(failoverOpt.SentinelAddrs))
	copy(sentinelAddrs, failoverOpt.SentinelAddrs)

	rand.Shuffle(len(sentinelAddrs), func(i, j int) {
		sentinelAddrs[i], sentinelAddrs[j] = sentinelAddrs[j], sentinelAddrs[i]
	})

	failover := &sentinelFailover{
		opt:           failoverOpt,
		sentinelAddrs: sentinelAddrs,
	}

	opt := failoverOpt.clientOptions()

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Call redis.NewFailoverClusterClient(opts) instead of NewFailoverClient when you need RouteByLatency.
  2. Set RouteByLatency to false (or omit it) if the sentinel client is what you actually want.

Example fix

// before
client := redis.NewFailoverClient(&redis.FailoverOptions{
    MasterName: "mymaster",
    SentinelAddrs: addrs,
    RouteByLatency: true, // panics
})

// after
client := redis.NewFailoverClusterClient(&redis.FailoverOptions{
    MasterName: "mymaster",
    SentinelAddrs: addrs,
    RouteByLatency: true,
})
Defensive patterns

Strategy: validation

Validate before calling

if opt.RouteByLatency {
    return errors.New("RouteByLatency requires NewFailoverClusterClient, not NewFailoverClient")
}

Prevention

When it happens

Trigger: Calling redis.NewFailoverClient with &redis.FailoverOptions{RouteByLatency: true, ...} set.

Common situations: Copy-pasting options from a ClusterClient configuration (where RouteByLatency is valid) into FailoverOptions; sharing a single options struct across multiple client types in a config layer.

Related errors


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