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
- Use asynq.RedisClientOpt, RedisClusterClientOpt, or RedisFailoverClientOpt to configure the server
- If you already hold a go-redis client, use asynq.NewServerFromRedisClient instead
- Make custom RedisConnOpt's MakeRedisClient return a value implementing redis.UniversalClient
- 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
- Use asynq.RedisClientOpt / RedisClusterClientOpt / RedisFailoverClientOpt for the server
- Use NewServerFromRedisClient when you already hold a go-redis client
- Keep custom MakeRedisClient implementations returning go-redis UniversalClient types
- Add a startup smoke test that constructs the Server with the production conn opt
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
- asynq: unsupported RedisConnOpt type %T
- inspeq: unsupported RedisConnOpt type %T
- asynq: unsupported RedisConnOpt type %T
- asynq: could not parse redis uri
- asynq: unsupported uri scheme
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)