{"id":"07944655b0842c24","repo":"go-redis/redis","slug":"circuit-breaker-reset-timeout-must-be-0","errorCode":null,"errorMessage":"circuit breaker reset timeout must be >= 0","messagePattern":"circuit breaker reset timeout must be >= 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"maintnotifications/errors.go","lineNumber":73,"sourceCode":"\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":55,"sourceCodeEnd":77,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/maintnotifications/errors.go#L55-L77","documentation":"Returned by Config.Validate() (maintnotifications/config.go:181-183) when Config.CircuitBreakerResetTimeout < 0. This is how long a circuit breaker stays open before probing the endpoint again (circuit_breaker.go:90). Zero is valid (probe immediately on next check); negatives are rejected.","triggerScenarios":"Setting Options.MaintNotificationsConfig.CircuitBreakerResetTimeout to a negative time.Duration, then constructing the client which runs Validate().","commonSituations":"A computed duration that goes negative (e.g. base - jitter where jitter > base); parsing a negative number with a time unit; using -1s as a 'disable' sentinel.","solutions":["Set CircuitBreakerResetTimeout to 0 (immediate probe) or a positive duration (default 60s).","Clamp computed durations: `if d < 0 { d = 0 }`.","Keep it reasonable (tens of seconds) to avoid hammering a dead endpoint."],"exampleFix":"// before\ncfg := &maintnotifications.Config{CircuitBreakerResetTimeout: -10 * time.Second}\n\n// after\ncfg := &maintnotifications.Config{CircuitBreakerResetTimeout: 60 * time.Second}","handlingStrategy":"validation","validationCode":"if cfg.CircuitBreakerResetTimeout < 0 {\n    cfg.CircuitBreakerResetTimeout = 60 * time.Second\n}\nif err := cfg.Validate(); err != nil {\n    return fmt.Errorf(\"maint config: %w\", err)\n}","typeGuard":"func validResetTimeout(d time.Duration) bool { return d >= 0 }","tryCatchPattern":null,"preventionTips":["Clamp computed durations to >=0.","Use 0 only if you want immediate half-open probing.","Validate duration fields together."],"tags":["maintnotifications","config","validation","circuit-breaker","timeout"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}