Skip to content

Exceptions

When a resilience operation fails, NResilience rethrows the original exception unchanged using ExceptionDispatchInfo. This preserves the original stack trace, ensuring that standard catch blocks - such as catch (HttpRequestException) or catch (SqlException) - continue to work as expected.

The library only introduces new exception types for failures it generates, such as deadlines it enforces or calls it refuses to make.

Accessing the attempt log

For any exception thrown by the library, the attempt log is stored in Exception.Data under the AttemptLog.DataKey. You can retrieve this log using AttemptLog.Of(exception).

CallRejectedException

A CallRejectedException is thrown when a guard refuses to execute a call.

MemberDescription
ReasonThe reason for the refusal: DependencyUnavailable for an open circuit breaker, or BudgetExhausted for a depleted retry budget.
AttemptsThe history of attempts that occurred before the call was rejected.
RetryAfterA hint indicating when the caller should retry the operation, if provided.

This exception is thrown no sooner than the rejection pause. Because the rejected call was never made, this exception reports the rejection itself; the exception from the previous attempt is contained as the inner exception.

DeadlineExceededException

A DeadlineExceededException occurs when the overall wall-clock budget for the entire call expires. This exception derives from TimeoutException.

MemberDescription
DeadlineThe budget that was exceeded.
AttemptsAll attempts that occurred before the deadline was reached.

AttemptTimeoutException

An AttemptTimeoutException is thrown when a single attempt exceeds its specific time ceiling. This exception derives from TimeoutException.

MemberDescription
TimeoutThe ceiling that the attempt exceeded.
AttemptsThe complete attempt log, if this was the final exception of the call.

The executor always classifies AttemptTimeoutException as Transient, regardless of the configured classifier.

RateLimitedException

A RateLimitedException is thrown when local admission control refuses to start an attempt. Nothing reached the dependency.

MemberDescription
LimiterThe name of the limiter that refused, or null if it was unnamed.
RetryAfterWhen the limiter said a permit would be available, if it said. Honored over the backoff curve.

The executor always classifies it as Verdict.Limited, regardless of the configured classifier - so it is retried on the throttled curve, is never counted against the breaker, and is never charged to the retry budget. Because the executor handles it directly, a Classifier never sees it; calling ClassifyException with one returns Permanent.

Throw it yourself from any limiter you bring, and it composes the same way. See Rate limiting.

ResilienceConfigurationException

A ResilienceConfigurationException is thrown when a policy, breaker setting, or budget parameter is invalid.

MemberDescription
ProblemsA collection of all configuration problems found.

This exception is thrown by Resilience.Validate(), BreakerSettings.Validate(), and the RetryBudget factories. It may also be thrown during DI registration or lazily during the first execution of a policy instance.

Caller cancellation

If the CancellationToken you provided is cancelled, an OperationCanceledException is thrown. This exception is never retried, counted as an attempt, converted into a timeout, or suppressed - even when using TryRunAsync.

Released under the MIT License.