Not all exceptions are equal. ADocumentation Index
Fetch the complete documentation index at: https://mintlify.com/danielfm/pybreaker/llms.txt
Use this file to discover all available pages before exploring further.
TimeoutError talking to your database is a signal that something is wrong with your infrastructure and the circuit breaker should respond. A ValueError raised because a caller passed bad input is a programming or user error — it says nothing about whether the downstream service is healthy, and tripping the circuit in response would be wrong. PyBreaker is designed around this distinction: it separates system errors from business exceptions and only counts the former toward the failure threshold.
What Counts as a Failure?
By default, any exception raised by the guarded function is treated as a system error and increments the failure counter. This is the safe default — if you have not told PyBreaker what to ignore, it assumes every exception might indicate an unhealthy dependency. Two important rules apply:- Exception subclasses are handled correctly. If you exclude
IOError, a subclass such asConnectionResetErroris also excluded, because PyBreaker usesissubclass()for the check. CircuitBreakerErroritself does not count as a new failure. When the circuit is already open and PyBreaker raisesCircuitBreakerErrorto reject a call, that rejection is not recorded as an additional failure — it would be circular to penalise the breaker for doing its job.
True to exclude it:
System Errors vs. Business Exceptions
System errors indicate that the downstream service itself is malfunctioning — the connection was refused, the socket timed out, the database driver returned an unexpected internal error. These are exactly the failures the circuit breaker is designed to track. Business exceptions are raised by correctly-functioning code to communicate domain-level outcomes: a record was not found, the user lacks permission, the submitted form is invalid. The downstream service responded correctly; the caller simply needs to handle the outcome. Tripping the circuit breaker on these exceptions would cause the breaker to open when the service is perfectly healthy.is_system_error()
PyBreaker exposes its internal classification logic through the is_system_error() method so you can verify that your exclusion rules are working as intended:
is_system_error() returns False for an exception, PyBreaker still re-raises it — the exception propagates to the caller normally — but the failure counter is not incremented and the circuit is unaffected.
Failure Counter Behavior
PyBreaker maintains two counters internally:| Counter | Attribute | Description |
|---|---|---|
| Failure counter | fail_counter | Consecutive system errors in closed state |
| Success counter | success_counter | Consecutive successful calls in half-open state |
- Each system error increments
fail_counterby 1. - Any successful call resets
fail_counterto 0. Failures must be consecutive to trip the breaker — a single success wipes the slate clean. - When
fail_counter >= fail_max, the circuit trips to open andfail_counteris not reset.
- No calls reach the guarded function, so neither counter changes.
fail_counterretains its value from when the circuit tripped.
- A successful trial call increments
success_counterby 1. - Once
success_counter >= success_threshold, the circuit closes and both counters reset to 0. - A failed trial call opens the circuit immediately;
success_counterresets to 0 when the open state is entered.
The throw_new_error_on_trip Option
When the circuit trips — i.e., the call that pushed fail_counter to fail_max — PyBreaker needs to decide what exception to raise to the caller.
Default behaviour (throw_new_error_on_trip=True): PyBreaker raises CircuitBreakerError instead of the original exception. This makes it easy to distinguish “the circuit just opened” from subsequent open-circuit rejections and from real downstream errors.
Alternative behaviour (throw_new_error_on_trip=False): PyBreaker re-raises the original exception — the one actually thrown by the guarded function — when the circuit trips. Subsequent calls while the circuit is open still raise CircuitBreakerError.
throw_new_error_on_trip=False, the original exception is re-raised rather than CircuitBreakerError.
