redis/go-redis · error

redis: CLIENT TRACKING OPTIN and OPTOUT are mutually exclusi

Error message

redis: CLIENT TRACKING OPTIN and OPTOUT are mutually exclusive

What it means

validateClientTrackingOptions rejects CLIENT TRACKING options where both OptIn and OptOut are true. The two modes are mutually exclusive on the Redis protocol side, so the client refuses the combination locally.

Source

Thrown at commands.go:628

		}
		args = appendClientTrackingOptions(args, opt)
	}
	cmd := NewStatusCmd(ctx, args...)
	_ = c(ctx, cmd)
	return cmd
}

// ClientTrackingOff disables tracking on the serving connection. See
// ClientTracking for the pooled-client and built-in-CSC caveats.
func (c cmdable) ClientTrackingOff(ctx context.Context) *StatusCmd {
	cmd := NewStatusCmd(ctx, "client", "tracking", "off")
	_ = c(ctx, cmd)
	return cmd
}

func validateClientTrackingOptions(opt *ClientTrackingOptions) error {
	if opt.OptIn && opt.OptOut {
		return errors.New("redis: CLIENT TRACKING OPTIN and OPTOUT are mutually exclusive")
	}
	if opt.Bcast && (opt.OptIn || opt.OptOut) {
		return errors.New("redis: CLIENT TRACKING BCAST cannot be combined with OPTIN or OPTOUT")
	}
	if len(opt.Prefixes) > 0 && !opt.Bcast {
		return errors.New("redis: CLIENT TRACKING PREFIX requires BCAST")
	}
	return nil
}

func appendClientTrackingOptions(args []interface{}, opt *ClientTrackingOptions) []interface{} {
	if opt.Redirect != 0 {
		args = append(args, "redirect", opt.Redirect)
	}
	if opt.Bcast {
		args = append(args, "bcast")
	}
	for _, p := range opt.Prefixes {

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Set only one of OptIn or OptOut to true.
  2. If intent was opt-in mode, set OptIn: true and leave OptOut as the zero value.
  3. Validate the options struct before calling ClientTracking.

Example fix

// before
rdb.ClientTracking(ctx, &redis.ClientTrackingOptions{OptIn: true, OptOut: true})
// after
rdb.ClientTracking(ctx, &redis.ClientTrackingOptions{OptIn: true})
Defensive patterns

Strategy: validation

Validate before calling

func validTracking(o *redis.ClientTrackingOptions) bool {
    return o != nil && !(o.OptIn && o.OptOut)
}

Try / catch

if err := rdb.ClientTracking(ctx, opt).Err(); err != nil {
    if strings.Contains(err.Error(), "OPTIN and OPTOUT are mutually exclusive") {
        // fix options and retry
    }
}

Prevention

When it happens

Trigger: Calling ClientTracking with ClientTrackingOptions{OptIn: true, OptOut: true}.

Common situations: Merging two option structs (one OPTIN, one OPTOUT) and passing the union; config files where both opt keys were set to true.

Related errors


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