{"id":"cb7e4d3175e038be","repo":"go-redis/redis","slug":"circuit-breaker-is-open-failing-fast","errorCode":null,"errorMessage":"circuit breaker is open, failing fast","messagePattern":"circuit breaker is open, failing fast","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"maintnotifications/errors.go","lineNumber":65,"sourceCode":"\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":47,"sourceCodeEnd":77,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/maintnotifications/errors.go#L47-L77","documentation":"Returned by performConnectionHandoff (handoff_worker.go:373) and CircuitBreaker.Execute (circuit_breaker.go:110,113,120) when the per-endpoint circuit breaker is Open — the target endpoint has failed >= CircuitBreakerFailureThreshold times and the reset timeout (CircuitBreakerResetTimeout) has not elapsed. The handoff fails fast (shouldRetry=false) rather than dialing a known-bad endpoint.","triggerScenarios":"Repeated handoff failures to a specific new endpoint open that endpoint's circuit breaker; subsequent MOVING handoffs to the same endpoint short-circuit with ErrCircuitBreakerOpen until resetTimeout passes, after which it transitions to half-open (circuit_breaker.go:100) to probe recovery.","commonSituations":"A target node is genuinely down/unreachable; wrong EndpointType returns an address the client can't reach, so every handoff fails and trips the breaker; failure threshold too low for a noisy network; reset timeout too long so recovery is slow.","solutions":["Verify the endpoint is actually reachable (the circuit is opening for a reason — check connectivity/DNS/firewall).","If failures are transient, raise CircuitBreakerFailureThreshold (default 5) and/or lower CircuitBreakerResetTimeout (default 60s) for faster recovery probing.","Correct EndpointType if the returned address is unroutable from the client.","Monitor via GetCircuitBreakerStats() to see which endpoints are repeatedly opening."],"exampleFix":"// before\ncfg := maintnotifications.DefaultConfig()\n// FailureThreshold 5, ResetTimeout 60s -> opens quickly on flaky net\n\n// after\ncfg := maintnotifications.DefaultConfig()\ncfg.CircuitBreakerFailureThreshold = 20\ncfg.CircuitBreakerResetTimeout = 15 * time.Second","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if errors.Is(err, maintnotifications.ErrCircuitBreakerOpen) {\n    // endpoint temporarily blocked; back off then retry. \n    // Investigate why the endpoint keeps failing.\n    time.Sleep(cfg.CircuitBreakerResetTimeout / 4)\n    return retryCommand(ctx, cmd)\n}","preventionTips":["Confirm endpoint reachability — the breaker opens for real failures.","Tune FailureThreshold/ResetTimeout for your network noise level.","Correct EndpointType to avoid unroutable advertised addresses.","Watch GetCircuitBreakerStats() to spot repeat offenders."],"tags":["maintnotifications","circuit-breaker","handoff","runtime","resilience"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}