go-redis/redis · info
shutdown
Error message
shutdown
What it means
Returned by queueHandoff (handoff_worker.go:292,296,306) when the worker manager's shutdown channel is closed — i.e. the maintenance manager is shutting down (Manager.Close) and will not accept new handoff requests. It is a graceful-shutdown sentinel; the affected connection is removed from the pool.
Source
Thrown at maintnotifications/errors.go:59
ErrInvalidNotification = errors.New(logs.InvalidNotificationError()) ) // connection handoff errors var ( // ErrConnectionMarkedForHandoff is returned when a connection is marked for handoff // and should not be used until the handoff is complete ErrConnectionMarkedForHandoff = errors.New(logs.ConnectionMarkedForHandoffErrorMessage) // ErrConnectionMarkedForHandoffWithState is returned when a connection is marked for handoff // and should not be used until the handoff is complete ErrConnectionMarkedForHandoffWithState = errors.New(logs.ConnectionMarkedForHandoffErrorMessage + " with state") // ErrConnectionInvalidHandoffState is returned when a connection is in an invalid state for handoff ErrConnectionInvalidHandoffState = errors.New(logs.ConnectionInvalidHandoffStateErrorMessage) ) // shutdown errors var ( // ErrShutdown is returned when the maintnotifications manager is shutdown ErrShutdown = errors.New(logs.ShutdownError()) ) // circuit breaker errors var ( // ErrCircuitBreakerOpen is returned when the circuit breaker is open ErrCircuitBreakerOpen = errors.New(logs.CircuitBreakerOpenErrorMessage) ) // circuit breaker configuration errors var ( // ErrInvalidCircuitBreakerFailureThreshold is returned when the circuit breaker failure threshold is invalid ErrInvalidCircuitBreakerFailureThreshold = errors.New(logs.InvalidCircuitBreakerFailureThresholdError()) // ErrInvalidCircuitBreakerResetTimeout is returned when the circuit breaker reset timeout is invalid ErrInvalidCircuitBreakerResetTimeout = errors.New(logs.InvalidCircuitBreakerResetTimeoutError()) // ErrInvalidCircuitBreakerMaxRequests is returned when the circuit breaker max requests is invalid ErrInvalidCircuitBreakerMaxRequests = errors.New(logs.InvalidCircuitBreakerMaxRequestsError()) )
View on GitHub (pinned to 36d97525cd)
Solutions
- Ensure you stop issuing commands (gracefully drain) before calling Close(), so no new handoffs are attempted during teardown.
- Treat ErrShutdown during shutdown as expected — log at debug, not error.
- Avoid repeatedly creating and closing clients in a hot path; reuse a long-lived client.
- If seen outside of an explicit shutdown, check for a double-Close or premature manager teardown.
Defensive patterns
Strategy: try-catch
Try / catch
if errors.Is(err, maintnotifications.ErrShutdown) {
// expected during client teardown; stop issuing commands and return.
return err
} Prevention
- Drain/stop traffic before calling Close().
- Reuse long-lived clients; avoid churn.
- Log ErrShutdown at debug, not error, during shutdown.
When it happens
Trigger: Client.Close() (or Manager shutdown) races with an incoming MOVING notification that tries to queue a handoff. queueHandoff selects on hwm.shutdown first/priority and returns ErrShutdown instead of enqueuing.
Common situations: Application shutdown coinciding with a server-side migration; a health-check/restart loop that tears down clients during cluster events; calling Close() from one goroutine while another is actively serving traffic that triggers maintenance notifications.
Related errors
- max handoff retries reached
- handoff queue is full, cannot queue new handoff requests - c
- invalid notification format
- connection is in invalid state for handoff
- circuit breaker is open, failing fast
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/fa3ec2113b45e676.json.
Report an issue: GitHub.