hibiken/asynq · critical

asynq: unsupported RedisConnOpt type %T

Error message

asynq: unsupported RedisConnOpt type %T

What it means

asynq.NewServer panics when the provided RedisConnOpt's MakeRedisClient() does not return a redis.UniversalClient. The server requires a go-redis UniversalClient for its broker operations, and any incompatible connection-option implementation causes this immediate panic instead of a returned error.

Solutions

  1. Use asynq.RedisClientOpt, RedisClusterClientOpt, or RedisFailoverClientOpt to configure the server
  2. If you already hold a go-redis client, use asynq.NewServerFromRedisClient instead
  3. Make custom RedisConnOpt's MakeRedisClient return a value implementing redis.UniversalClient
  4. Add a startup type check: if _, ok := r.MakeRedisClient().(redis.UniversalClient); !ok { return a clear config error before calling NewServer }

Example fix

// before
srv := asynq.NewServer(myRedigoOpt{}, asynq.Config{}) // panics

// after
srv := asynq.NewServer(asynq.RedisClientOpt{Addr: "localhost:6379"}, asynq.Config{Concurrency: 10})
Defensive patterns

Strategy: validation

Validate before calling

opt := asynq.RedisClientOpt{Addr: ":6379"}
if _, ok := opt.MakeRedisClient().(redis.UniversalClient); !ok {
    log.Fatal("server RedisConnOpt must yield a go-redis UniversalClient")
}
srv := asynq.NewServer(opt, asynq.Config{})

Type guard

func serverConnOptValid(r asynq.RedisConnOpt) bool {
    _, ok := r.MakeRedisClient().(redis.UniversalClient)
    return ok
}

Prevention

When it happens

Trigger: Constructing asynq.NewServer with a custom RedisConnOpt whose MakeRedisClient returns nil or a non-go-redis client; passing a wrapper/adaptor type; using a conn-opt from a mismatched go-redis major version; passing an unvalidated config-driven conn opt.

Common situations: Custom RedisConnOpt implementations written against a different Redis library; DI containers supplying the wrong option type; upgrading go-redis so the UniversalClient interface no longer matches what MakeRedisClient returns.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07). Data as JSON: /api/errors/8a5e39c19dee0265. Report an issue: GitHub.

Appendix: source

Thrown at server.go:434

	defaultShutdownTimeout = 8 * time.Second

	defaultHealthCheckInterval = 15 * time.Second

	defaultDelayedTaskCheckInterval = 5 * time.Second

	defaultGroupGracePeriod = 1 * time.Minute

	defaultJanitorInterval = 8 * time.Second

	defaultJanitorBatchSize = 100
)

// NewServer returns a new Server given a redis connection option
// and server configuration.
func NewServer(r RedisConnOpt, cfg Config) *Server {
	redisClient, ok := r.MakeRedisClient().(redis.UniversalClient)
	if !ok {
		panic(fmt.Sprintf("asynq: unsupported RedisConnOpt type %T", r))
	}
	server := NewServerFromRedisClient(redisClient, cfg)
	server.sharedConnection = false
	return server
}

// NewServerFromRedisClient returns a new instance of Server given a redis.UniversalClient
// and server configuration
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.
func NewServerFromRedisClient(c redis.UniversalClient, cfg Config) *Server {
	baseCtxFn := cfg.BaseContext
	if baseCtxFn == nil {
		baseCtxFn = context.Background
	}
	n := cfg.Concurrency
	if n < 1 {
		n = runtime.NumCPU()
	}

View on GitHub (pinned to d135f1439b)