{"id":"f1162d990b07c35d","repo":"go-redis/redis","slug":"maxhandoffretries-must-be-between-1-and-10","errorCode":null,"errorMessage":"MaxHandoffRetries must be between 1 and 10","messagePattern":"MaxHandoffRetries must be between 1 and 10","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"maintnotifications/errors.go","lineNumber":23,"sourceCode":"\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())\n)\n\n// Notification errors\nvar (\n\t// ErrInvalidNotification is returned when a notification is in an invalid format\n\tErrInvalidNotification = errors.New(logs.InvalidNotificationError())","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/maintnotifications/errors.go#L5-L41","documentation":"Returned by Config.Validate() (maintnotifications/config.go:199-201) when Config.MaxHandoffRetries is outside the allowed 1-10 range. MaxHandoffRetries bounds how many times a failing connection handoff is retried before the connection is dropped (handoff_worker.go:407). Zero is not allowed because at least one attempt is required; >10 is rejected to prevent runaway retry loops.","triggerScenarios":"Setting Options.MaintNotificationsConfig.MaxHandoffRetries to 0 or a value >10, then constructing the client which runs Validate().","commonSituations":"Setting it to 0 intending 'no retries' (use ModeDisabled instead); bumping it very high to 'never give up' during testing; computing it from a multiplier that overflows the cap.","solutions":["Set MaxHandoffRetries to a value between 1 and 10 inclusive (default is 3).","If you want maintenance handoffs fully off, set Mode = ModeDisabled rather than zeroing retries.","Clamp any externally sourced value into [1,10] before assigning."],"exampleFix":"// before\ncfg := &maintnotifications.Config{MaxHandoffRetries: 0}\n\n// after\ncfg := &maintnotifications.Config{MaxHandoffRetries: 3}","handlingStrategy":"validation","validationCode":"if cfg.MaxHandoffRetries < 1 || cfg.MaxHandoffRetries > 10 {\n    cfg.MaxHandoffRetries = 3\n}\nif err := cfg.Validate(); err != nil {\n    return fmt.Errorf(\"maint config: %w\", err)\n}","typeGuard":"func validMaxHandoffRetries(n int) bool { return n >= 1 && n <= 10 }","tryCatchPattern":null,"preventionTips":["Keep MaxHandoffRetries in [1,10]; use ModeDisabled to turn handoffs off.","Clamp externally sourced values.","Test the config loader's bounds."],"tags":["maintnotifications","config","validation","handoff","retry"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}