go-redis/redis · error

redisotel: %T not supported

Error message

redisotel: %T not supported

What it means

Returned by InstrumentMetrics (extra/redisotel/metrics.go:55) when the passed redis.UniversalClient is not one of the supported concrete types (*redis.Client, *redis.ClusterClient, *redis.Ring) and no explicit poolName was configured. The type switch falls through to the default case because the client wrapper type is unrecognized.

Source

Thrown at extra/redisotel/metrics.go:55

			metric.WithInstrumentationVersion("semver:"+redis.Version()),
		)
	}
	if conf.poolName == "" {
		switch rdb := rdb.(type) {
		case *redis.Client:
			conf.poolName = rdb.Options().Addr
		case *redis.ClusterClient:
			for _, addr := range rdb.Options().Addrs {
				conf.poolName = addr
				break
			}
		case *redis.Ring:
			for _, addr := range rdb.Options().Addrs {
				conf.poolName = addr
				break
			}
		default:
			return fmt.Errorf("redisotel: %T not supported", rdb)
		}
	}
	conf.attrs = append(conf.attrs, attribute.String("pool.name", conf.poolName))

	var state *metricsState
	if conf.closeChan != nil {
		state = &metricsState{
			registrations: make([]metric.Registration, 0),
			closed:        false,
			mutex:         sync.Mutex{},
		}

		go func() {
			<-conf.closeChan

			state.mutex.Lock()
			state.closed = true

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Pass the concrete *redis.Client, *redis.ClusterClient, or *redis.Ring directly to InstrumentMetrics
  2. Use the WithPoolName option to pre-set conf.poolName so the type switch is skipped entirely
  3. If using a UniversalClient wrapper, unwrap it to the underlying concrete client before passing it to InstrumentMetrics

Example fix

// before - passing a UniversalClient wrapper
var rdb redis.UniversalClient = getUniversalClient()
err := redisotel.InstrumentMetrics(rdb)
// returns: redisotel: *universalClient not supported

// after - pass the concrete type, or set poolName explicitly
err := redisotel.InstrumentMetrics(rdb.(*redis.Client))
// or:
err := redisotel.InstrumentMetrics(rdb, redisotel.WithPoolName("my-pool"))
Defensive patterns

Strategy: type-guard

Type guard

// Check the concrete client type before calling InstrumentMetrics
switch rdb.(type) {
case *redis.Client, *redis.ClusterClient, *redis.Ring:
    // supported - proceed
default:
    log.Fatalf("redisotel.InstrumentMetrics does not support client type %T; unwrap or set poolName", rdb)
}

Try / catch

if err := redisotel.InstrumentMetrics(rdb, redisotel.WithPoolName("my-pool")); err != nil {
    if strings.Contains(err.Error(), "not supported") {
        log.Errorf("unsupported client type %T; pass *redis.Client/*ClusterClient/*Ring or set poolName", rdb)
    }
}

Prevention

When it happens

Trigger: Calling redisotel.InstrumentMetrics with a client type other than *redis.Client, *redis.ClusterClient, or *redis.Ring without setting the WithMetricsDestinationAddr/WithPoolName option to pre-populate conf.poolName.

Common situations: Passing a redis.UniversalClient that wraps one of the supported types but is itself a different concrete type; using a custom client implementation that satisfies the UniversalClient interface but is not one of the three built-in types; wrapping the client in a decorator or mock.

Related errors


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