{"record":{"id":"a0ec2de9a467e64d","repo":"hibiken/asynq","slug":"asynq-unsupported-redisconnopt-type-t","errorCode":null,"errorMessage":"asynq: unsupported RedisConnOpt type %T","messagePattern":"asynq: unsupported RedisConnOpt type %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"client.go","lineNumber":39,"sourceCode":"\n// A Client is responsible for scheduling tasks.\n//\n// A Client is used to register tasks that should be processed\n// immediately or some time in the future.\n//\n// Clients are safe for concurrent use by multiple goroutines.\ntype Client struct {\n\tbroker base.Broker\n\t// When a Client has been created with an existing Redis connection, we do\n\t// not want to close it.\n\tsharedConnection bool\n}\n\n// NewClient returns a new Client instance given a redis connection option.\nfunc NewClient(r RedisConnOpt) *Client {\n\tredisClient, ok := r.MakeRedisClient().(redis.UniversalClient)\n\tif !ok {\n\t\tpanic(fmt.Sprintf(\"asynq: unsupported RedisConnOpt type %T\", r))\n\t}\n\tclient := NewClientFromRedisClient(redisClient)\n\tclient.sharedConnection = false\n\treturn client\n}\n\n// NewClientFromRedisClient returns a new instance of Client given a redis.UniversalClient\n// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.\nfunc NewClientFromRedisClient(c redis.UniversalClient) *Client {\n\treturn &Client{broker: rdb.NewRDB(c), sharedConnection: true}\n}\n\ntype OptionType int\n\nconst (\n\tMaxRetryOpt OptionType = iota\n\tQueueOpt\n\tTimeoutOpt","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/hibiken/asynq/blob/d135f1439bee74e989b7f9b41ecd542cc87f024a/client.go#L21-L57","documentation":"asynq.NewClient panics when the provided RedisConnOpt's MakeRedisClient() method does not return a value implementing redis.UniversalClient (go-redis). NewClient only accepts connection options whose underlying client is a go-redis UniversalClient; any custom or foreign RedisConnOpt implementation triggers this panic immediately at construction time.","triggerScenarios":"Passing a RedisConnOpt whose MakeRedisClient() returns nil, a raw *redis.Client typed as something else, or a fully custom type that does not implement the interface; constructing asynq.NewClient with a hand-rolled adapter struct; passing a zero-value custom conn option.","commonSituations":"Wrapping a redis cluster/sentinel setup in a custom config struct instead of asynq.RedisClientOpt/RedisClusterClientOpt/RedisFailoverClientOpt; upgrading go-redis versions so the UniversalClient interface no longer matches; typos where a config object that merely resembles RedisConnOpt is passed in.","solutions":["Use one of the built-in options: asynq.RedisClientOpt, RedisClusterClientOpt, or RedisFailoverClientOpt","If using a custom RedisConnOpt, make MakeRedisClient() return a *redis.Client / *redis.ClusterClient / *redis.UniversalClient that satisfies redis.UniversalClient","If you already hold a go-redis client, use asynq.NewClientFromRedisClient instead of NewClient","Check the concrete type returned by MakeRedisClient with %T and confirm it implements redis.UniversalClient"],"exampleFix":"// before\nconn := myCustomRedisWrapper{addr: \":6379\"} // MakeRedisClient returns the wrapper\nclient := asynq.NewClient(conn)\n\n// after\nclient := asynq.NewClient(asynq.RedisClientOpt{Addr: \":6379\"})\n// or, with an existing go-redis client:\nclient := asynq.NewClientFromRedisClient(rdb)","handlingStrategy":"validation","validationCode":"opt := asynq.RedisClientOpt{Addr: \":6379\"}\nif _, ok := opt.MakeRedisClient().(redis.UniversalClient); !ok {\n    log.Fatal(\"RedisConnOpt does not produce a go-redis UniversalClient\")\n}\nclient := asynq.NewClient(opt)","typeGuard":"func isValidRedisConnOpt(r asynq.RedisConnOpt) bool {\n    _, ok := r.MakeRedisClient().(redis.UniversalClient)\n    return ok\n}","tryCatchPattern":null,"preventionTips":["Prefer built-in RedisClientOpt / RedisClusterClientOpt / RedisFailoverClientOpt over custom implementations","Use NewClientFromRedisClient when you already have a go-redis client","Keep go-redis version aligned with the version asynq was built against","Smoke-test Redis construction in an init/unit test so the panic surfaces at CI, not in production startup"],"tags":["redis","panic","configuration","go"],"backgroundTag":"type-mismatch","analyzedSha":"d135f1439bee74e989b7f9b41ecd542cc87f024a","analyzedAt":"2026-09-07T19:02:34.660Z","contentChangedAt":"2026-09-07T19:02:34.660Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}