{"id":"fa3ec2113b45e676","repo":"go-redis/redis","slug":"shutdown","errorCode":null,"errorMessage":"shutdown","messagePattern":"shutdown","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"info","filePath":"maintnotifications/errors.go","lineNumber":59,"sourceCode":"\tErrInvalidNotification = errors.New(logs.InvalidNotificationError())\n)\n\n// connection handoff errors\nvar (\n\t// ErrConnectionMarkedForHandoff is returned when a connection is marked for handoff\n\t// and should not be used until the handoff is complete\n\tErrConnectionMarkedForHandoff = errors.New(logs.ConnectionMarkedForHandoffErrorMessage)\n\t// ErrConnectionMarkedForHandoffWithState is returned when a connection is marked for handoff\n\t// and should not be used until the handoff is complete\n\tErrConnectionMarkedForHandoffWithState = errors.New(logs.ConnectionMarkedForHandoffErrorMessage + \" with state\")\n\t// ErrConnectionInvalidHandoffState is returned when a connection is in an invalid state for handoff\n\tErrConnectionInvalidHandoffState = errors.New(logs.ConnectionInvalidHandoffStateErrorMessage)\n)\n\n// shutdown errors\nvar (\n\t// ErrShutdown is returned when the maintnotifications manager is shutdown\n\tErrShutdown = errors.New(logs.ShutdownError())\n)\n\n// circuit breaker errors\nvar (\n\t// ErrCircuitBreakerOpen is returned when the circuit breaker is open\n\tErrCircuitBreakerOpen = errors.New(logs.CircuitBreakerOpenErrorMessage)\n)\n\n// circuit breaker configuration errors\nvar (\n\t// ErrInvalidCircuitBreakerFailureThreshold is returned when the circuit breaker failure threshold is invalid\n\tErrInvalidCircuitBreakerFailureThreshold = errors.New(logs.InvalidCircuitBreakerFailureThresholdError())\n\t// ErrInvalidCircuitBreakerResetTimeout is returned when the circuit breaker reset timeout is invalid\n\tErrInvalidCircuitBreakerResetTimeout = errors.New(logs.InvalidCircuitBreakerResetTimeoutError())\n\t// ErrInvalidCircuitBreakerMaxRequests is returned when the circuit breaker max requests is invalid\n\tErrInvalidCircuitBreakerMaxRequests = errors.New(logs.InvalidCircuitBreakerMaxRequestsError())\n)\n","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/maintnotifications/errors.go#L41-L77","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, maintnotifications.ErrShutdown) {\n    // expected during client teardown; stop issuing commands and return.\n    return err\n}","preventionTips":["Drain/stop traffic before calling Close().","Reuse long-lived clients; avoid churn.","Log ErrShutdown at debug, not error, during shutdown."],"tags":["maintnotifications","shutdown","lifecycle","runtime"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}