{"id":"b991147460021fb7","repo":"go-redis/redis","slug":"max-handoff-retries-reached","errorCode":null,"errorMessage":"max handoff retries reached","messagePattern":"max handoff retries reached","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"maintnotifications/errors.go","lineNumber":17,"sourceCode":"package maintnotifications\n\nimport (\n\t\"errors\"\n\n\t\"github.com/redis/go-redis/v9/internal/maintnotifications/logs\"\n)\n\n// Configuration errors\nvar (\n\tErrInvalidRelaxedTimeout             = errors.New(logs.InvalidRelaxedTimeoutError())\n\tErrInvalidHandoffTimeout             = errors.New(logs.InvalidHandoffTimeoutError())\n\tErrInvalidHandoffWorkers             = errors.New(logs.InvalidHandoffWorkersError())\n\tErrInvalidHandoffQueueSize           = errors.New(logs.InvalidHandoffQueueSizeError())\n\tErrInvalidPostHandoffRelaxedDuration = errors.New(logs.InvalidPostHandoffRelaxedDurationError())\n\tErrInvalidEndpointType               = errors.New(logs.InvalidEndpointTypeError())\n\tErrInvalidMaintNotifications         = errors.New(logs.InvalidMaintNotificationsError())\n\tErrMaxHandoffRetriesReached          = errors.New(logs.MaxHandoffRetriesReachedError())\n\n\t// Configuration validation errors\n\n\t// ErrInvalidHandoffRetries is returned when the number of handoff retries is invalid\n\tErrInvalidHandoffRetries = errors.New(logs.InvalidHandoffRetriesError())\n)\n\n// Integration errors\nvar (\n\t// ErrInvalidClient is returned when the client does not support push notifications\n\tErrInvalidClient = errors.New(logs.InvalidClientError())\n)\n\n// Handoff errors\nvar (\n\t// ErrHandoffQueueFull is returned when the handoff queue is full\n\tErrHandoffQueueFull = errors.New(logs.HandoffQueueFullError())","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/maintnotifications/errors.go#L1-L35","documentation":"Returned by performHandoffInternal (handoff_worker.go:407-412) when IncrementAndGetHandoffRetries exceeds Config.MaxHandoffRetries. Unlike other handoff errors this one is non-retryable (shouldRetry=false): the connection has failed to relocate to its new endpoint too many times and is removed from the pool rather than being queued again.","triggerScenarios":"A connection receives a MOVING notification, is handed off, but the new endpoint is repeatedly unreachable or the dial keeps failing. Each retry increments the counter; once it crosses MaxHandoffRetries (default 3), performConnectionHandoff returns ErrMaxHandoffRetriesReached and processHandoffRequest closes the connection (handoff_worker.go:247-251).","commonSituations":"The new endpoint returned by MOVING is wrong/unreachable (firewall, DNS, wrong EndpointType for the network); the target node is down during a multi-shard migration storm; HandoffTimeout too short causing repeated dial aborts that each count as a retry.","solutions":["Verify the new endpoint is reachable from the client host (telnet/curl the host:port the MOVING notification advertised).","Check EndpointType: if the server returns an internal IP/FQDN the client cannot route to, switch to an external type or fix network/DNS.","If the endpoint is genuinely flaky but recoverable, raise Config.MaxHandoffRetries (1-10) to give handoff more attempts.","Increase HandoffTimeout so transient slow dials don't each burn a retry."],"exampleFix":"// before\ncfg := maintnotifications.DefaultConfig() // MaxHandoffRetries: 3\n\n// after\ncfg := maintnotifications.DefaultConfig()\ncfg.MaxHandoffRetries = 5\ncfg.HandoffTimeout = 30 * time.Second\ncfg.EndpointType = maintnotifications.EndpointTypeExternalIP","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, maintnotifications.ErrMaxHandoffRetriesReached) {\n    // connection was dropped; the next command will use a fresh pooled conn.\n    // Investigate endpoint reachability / EndpointType, then retry the command.\n}","preventionTips":["Verify MOVING-advertised endpoints are routable from the client host.","Pick the correct EndpointType for your network topology.","Raise MaxHandoffRetries (1-10) for genuinely flaky-but-recoverable endpoints.","Monitor handoff-failure logs (logs.HandoffFailed)."],"tags":["maintnotifications","handoff","retry","runtime"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}