HCR040¶
Do not stack duplicate resilience handlers.
Why¶
Stacking duplicate resilience handlers can duplicate retries, timeouts, circuit breakers, and rate limiters. That can amplify traffic during outages and make retry behavior difficult to reason about.
Bad¶
services.AddHttpClient<GitHubClient>()
.AddStandardResilienceHandler()
.AddStandardResilienceHandler();
services.AddHttpClient<GitHubClient>()
.AddResilienceHandler("github", builder => { })
.AddResilienceHandler("github", builder => { });
Better¶
services.AddHttpClient<GitHubClient>()
.AddResilienceHandler("read", builder => { })
.AddResilienceHandler("write", builder => { });
Current Detection¶
Reports duplicate AddStandardResilienceHandler() calls and duplicate same-name AddResilienceHandler("name", ...) calls in the same fluent registration chain when the chain visibly comes from AddHttpClient(...) returning an IHttpClientBuilder shape or from an IHttpClientBuilder receiver. Parentheses and null-forgiving operators are treated as transparent between fluent chain segments. It also reports repeated AddStandardResilienceHandler() calls on the same visible IHttpClientBuilder receiver in one block when that receiver has not been reassigned between calls. Custom handler names are matched when they are string literals or compile-time string constants, with parentheses and null-forgiving operators treated as transparent. Qualified builder type names are matched against Microsoft.Extensions.DependencyInjection.IHttpClientBuilder, resolved standard and named handler methods must come from the framework extension namespace, different custom resilience handler names are allowed, and lookalike AddHttpClient(...).AddStandardResilienceHandler() chains or custom handler extensions are skipped.
Code Fix¶
The code fix removes the duplicate resilience handler call from the fluent chain and preserves comments/trivia attached to the removed call so nearby policy context is not lost.
Suppression¶
Prefer removing the duplicate handler. Suppress only when the chain is intentionally composed by a custom abstraction and duplicate runtime handlers cannot actually be produced.