{"id":"00dd079cca1e1ed5","repo":"go-redis/redis","slug":"redis-client-is-closed","errorCode":null,"errorMessage":"redis: client is closed","messagePattern":"redis: client is closed","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/pool/pool.go","lineNumber":58,"sourceCode":"\tCloseReasonMaintNotificationsDisabled = \"maintnotifications_disabled\"\n)\n\n// Metric state constants for connection state tracking.\n// These represent the logical state of a connection from a metrics perspective,\n// not the internal state machine state (ConnState).\nconst (\n\t// MetricStateIdle indicates the connection is idle in the pool,\n\t// ready to be acquired.\n\tMetricStateIdle = \"idle\"\n\n\t// MetricStateUsed indicates the connection is currently being used\n\t// by a client operation.\n\tMetricStateUsed = \"used\"\n)\n\nvar (\n\t// ErrClosed performs any operation on the closed client will return this error.\n\tErrClosed = errors.New(\"redis: client is closed\")\n\n\t// ErrPoolExhausted is returned from a pool connection method\n\t// when the maximum number of database connections in the pool has been reached.\n\tErrPoolExhausted = errors.New(\"redis: connection pool exhausted\")\n\n\t// ErrPoolTimeout timed out waiting to get a connection from the connection pool.\n\tErrPoolTimeout = errors.New(\"redis: connection pool timeout\")\n\n\t// ErrConnUnusableTimeout is returned when a connection is not usable and we timed out trying to mark it as unusable.\n\tErrConnUnusableTimeout = errors.New(\"redis: timed out trying to mark connection as unusable\")\n\n\t// errHookRequestedRemoval is returned when a hook requests connection removal.\n\terrHookRequestedRemoval = errors.New(\"hook requested removal\")\n\n\t// errConnNotPooled is returned when trying to return a non-pooled connection to the pool.\n\terrConnNotPooled = errors.New(\"connection not pooled\")\n\n\t// errConnEvictedIdle is passed to OnRemove hooks when a pooled connection is evicted on","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/internal/pool/pool.go#L40-L76","documentation":"pool.ErrClosed is returned by any pool/client operation attempted after Close() (pool.go:57-58). Once the client or pool is closed, Get/NewConn/Put and derived operations (pubsub open, etc.) fail immediately with this sentinel rather than attempting I/O.","triggerScenarios":"Calling client.Get/Set/Subscribe (or pool.Get) after client.Close() has been invoked; common in shutdown ordering bugs, reusing a client across goroutines where one closes it, or tests not resetting the client.","commonSituations":"Graceful-shutdown races, deferred Close() running before an in-flight op, or a long-lived shared client closed by one consumer.","solutions":["Do not reuse a client after Close(); create a new client for the new lifecycle.","Coordinate close with a WaitGroup/context so in-flight ops finish first.","Guard with client.(*redis.Client) and a closed flag, or check errors.Is(err, redis.ErrClosed)."],"exampleFix":"// before\nclient.Close()\nclient.Get(ctx, key) // ErrClosed\n// after\nclient.Close()\nclient = nil\n// on next use, lazily construct a new client","handlingStrategy":"validation","validationCode":"// Track lifecycle yourself; go-redis has no public Closed() check.\n// Don't reuse after Close(); recreate when needed.\nif client == nil {\n    client = redis.NewClient(opts)\n}","typeGuard":"// There is no public Closed() accessor on *redis.Client.\n// Track closure in your own wrapper.\ntype safeClient struct{ c *redis.Client; closed bool }","tryCatchPattern":"err := client.Get(ctx, key).Err()\nif errors.Is(err, redis.ErrClosed) {\n    // recreate the client for the new lifecycle\n    client = redis.NewClient(client.Options())\n}","preventionTips":["Never reuse a client after Close(); nil the reference.","Coordinate shutdown so in-flight ops complete before Close().","Own a single client lifecycle per logical service."],"tags":["pool","lifecycle","closed","client"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}