hibiken/asynq · warning
redis connection is shared so the Inspector can't be closed…
Error message
redis connection is shared so the Inspector can't be closed through asynq
What it means
Inspector.Close refuses to close a Redis connection that the Inspector shares with another client (created via NewInspectorFromRedisClient or similar sharing constructors). Closing the shared connection would break the other asynq components using it, so the library returns this error instead of closing. The caller owns the connection in that case and must close it themselves.
Solutions
- Track connection ownership yourself: call Close on the original redis client you passed in, not on the shared Inspector.
- Construct the Inspector with its own connection (asynq.NewInspector(redisAddr)) if you need Inspector.Close to work.
- Guard shutdown code: skip inspector.Close() when the Inspector was built from a shared client.
- Log and ignore this specific error during teardown if closing the shared connection elsewhere.
Example fix
// before
inspector := asynq.NewInspectorFromRedisClient(rdb)
defer inspector.Close() // errors: connection is shared
// after
inspector := asynq.NewInspectorFromRedisClient(rdb)
defer func() {
if err := inspector.Close(); err != nil {
log.Println("inspector uses shared connection; closing owner rdb instead")
}
rdb.Close()
}() Defensive patterns
Strategy: try-catch
Validate before calling
// track how the inspector was created
func closableInspector(shared bool, i *asynq.Inspector) bool { return !shared } Try / catch
if err := inspector.Close(); err != nil && strings.Contains(err.Error(), "connection is shared") {
// close the owning redis client instead
rdb.Close()
} Prevention
- Track ownership of the redis client passed to NewInspectorFromRedisClient.
- Use defer on the original client, not the shared Inspector, for cleanup.
- Create a dedicated Inspector if you rely on Close().
- During shutdown, close each component in the order you created them.
When it happens
Trigger: Calling Inspector.Close() on an Inspector constructed from a shared redis.UniversalClient — e.g. tests or apps that pass one redis client to both asynq.Client and asynq.NewInspectorFromRedisClient, then call inspector.Close().
Common situations: Sharing a single redis.Client across Client, Scheduler, and Inspector for connection pooling; test cleanup/deferred Close on a shared-connection Inspector; embedding the Inspector in a service that closes all resources on shutdown.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- failed to get queue names
- failed to get queue info
- redis command failed
- task id conflicts with another task
- testutil: redis is down
AI-assisted analysis of hibiken/asynq@d135f1439b (2026-09-07).
Data as JSON: /api/errors/a7b8bba2b3ff96d0.
Report an issue: GitHub.
Appendix: source
Thrown at inspector.go:52
}
inspector := NewInspectorFromRedisClient(c)
inspector.sharedConnection = false
return inspector
}
// NewInspectorFromRedisClient returns a new instance of Inspector given a redis.UniversalClient
// Warning: The underlying redis connection pool will not be closed by Asynq, you are responsible for closing it.
func NewInspectorFromRedisClient(c redis.UniversalClient) *Inspector {
return &Inspector{
rdb: rdb.NewRDB(c),
sharedConnection: true,
}
}
// Close closes the connection with redis.
func (i *Inspector) Close() error {
if i.sharedConnection {
return fmt.Errorf("redis connection is shared so the Inspector can't be closed through asynq")
}
return i.rdb.Close()
}
// Queues returns a list of all queue names.
func (i *Inspector) Queues() ([]string, error) {
return i.rdb.AllQueues()
}
// Groups returns a list of all groups within the given queue.
func (i *Inspector) Groups(queue string) ([]*GroupInfo, error) {
stats, err := i.rdb.GroupStats(queue)
if err != nil {
return nil, err
}
var res []*GroupInfo
for _, s := range stats {
res = append(res, &GroupInfo{View on GitHub (pinned to d135f1439b)