Skip to content

Classifier

The Classifier is a sealed class used to categorize the outcome of an attempt. It is immutable; every modification returns a new instance.

MemberDescription
Classifier.DefaultClassifies TimeoutException, IOException, and SocketException as Transient. All other exceptions are Permanent.
Classifier.HttpExtends Default by adding HttpRequestException as Transient and including a status-code rule for HttpResponseMessage.
Classifier.RetryEverythingContains no specific rules; every exception is classified as Transient.
On<TException>(Verdict)Assigns a fixed verdict to a specific exception type and its subclasses.
On<TException>(Func<TException, Verdict>)Assigns a verdict based on a predicate that can inspect the exception.
OnResult<T>(Func<T, Verdict>)Assigns a verdict to a returned value. The type T must match exactly.
ClassifyException(Exception)Returns the verdict for a given exception.
ClassifyResult<T>(T)Returns the verdict for a given result. Returns Verdict.Ok if no rule is registered for type T.
ToString()Returns a list of all rules in evaluation order, including the default verdict for unrecognized exceptions.

Rules are evaluated in reverse order of addition; the most recently added rule takes precedence.

HTTP status-code rules

Classifier.Http uses the following rules for HttpResponseMessage outcomes:

StatusVerdict
429Throttled (includes Retry-After if present)
503 with Retry-AfterThrottled (includes Retry-After)
Other 5xx and 408Transient
All other statusesOk

The Retry-After value is supported as both a delta-seconds value and an HTTP date. Both are converted to a TimeSpan and floored at zero.

Verdict

Verdict is a readonly struct that describes the outcome of an attempt.

MemberDescription
KindThe VerdictKind of the outcome.
RetryAfterA server-provided or limiter-provided delay that is honored over the standard backoff curve. This is null if there was no pushback.
SelfImposedtrue when the verdict came from local admission control rather than from the dependency. The retry budget is not charged for a self-imposed verdict. false for every other verdict, including default.
Verdict.OkThe call succeeded.
Verdict.TransientA failure that may not recur.
Verdict.PermanentA failure that will recur.
Verdict.Throttled(TimeSpan?)The dependency is defending itself, potentially with a suggested retry delay.
Verdict.Limited(TimeSpan?)A limiter in this process refused the attempt. Kind is Throttled and SelfImposed is true.

Verdict implements value equality, and SelfImposed is part of it: Verdict.Throttled() and Verdict.Limited() are not equal. ToString() prints a human-readable summary, such as Throttled (retry after 2s) or Throttled (self-imposed, retry after 2s).

VerdictKind

VerdictKind determines how the executor handles the outcome.

ValueRetried?Counted against the breaker?
OkNo (returned)Yes (sampled as success)
TransientYes (short backoff curve)Yes
ThrottledYes (long backoff curve or Retry-After)No (dependency is working as intended)
PermanentNoNo (treated as a client-side error)

Special cases

Three specific verdicts are produced by the executor itself and cannot be overridden by a classifier:

  1. Attempt Timeout: Classified as Transient.
  2. Caller Cancellation: Not classified as a failure.
  3. RateLimitedException: Classified as Verdict.Limited, so no classifier can turn a refusal this process imposed on itself into evidence against the dependency.

Note: If a classifier identifies an exception as Ok, the executor treats it as Permanent, because an exception cannot be converted into a return value.

Released under the MIT License.