App-vNext/Polly · error · KeyNotFoundException
Unable to find a generic resilience pipeline of '{typeof(TRe
Error message
Unable to find a generic resilience pipeline of '{typeof(TResult).Name}' associated with the key '{key}'. Please ensure that either the generic resilience pipeline or the generic builder is registered. What it means
The generic GetPipeline<TResult>(key) throws KeyNotFoundException when no generic pipeline or generic builder for that exact TResult was registered under the key. Generic and non-generic pipelines live in separate namespaces per key, so a non-generic registration will not satisfy a generic lookup.
Source
Thrown at src/Polly.Core/Registry/ResiliencePipelineProvider.cs:43
throw new KeyNotFoundException($"Unable to find a resilience pipeline associated with the key '{key}'. " +
$"Please ensure that either the resilience pipeline or the builder is registered.");
}
/// <summary>
/// Retrieves a generic resilience pipeline from the provider using the specified key.
/// </summary>
/// <typeparam name="TResult">The type of result that the resilience pipeline handles.</typeparam>
/// <param name="key">The key used to identify the resilience pipeline.</param>
/// <returns>The resilience pipeline associated with the specified key.</returns>
/// <exception cref="KeyNotFoundException">Thrown when no resilience pipeline is found for the specified key.</exception>
public virtual ResiliencePipeline<TResult> GetPipeline<TResult>(TKey key)
{
if (TryGetPipeline<TResult>(key, out var pipeline))
{
return pipeline;
}
throw new KeyNotFoundException($"Unable to find a generic resilience pipeline of '{typeof(TResult).Name}' associated with the key '{key}'. " +
$"Please ensure that either the generic resilience pipeline or the generic builder is registered.");
}
/// <summary>
/// Tries to get a resilience pipeline from the provider using the specified key.
/// </summary>
/// <param name="key">The key used to identify the resilience pipeline.</param>
/// <param name="pipeline">The output resilience pipeline if found, <see langword="null"/> otherwise.</param>
/// <returns><see langword="true"/> if the pipeline was found, <see langword="false"/> otherwise.</returns>
public abstract bool TryGetPipeline(TKey key, [NotNullWhen(true)] out ResiliencePipeline? pipeline);
/// <summary>
/// Tries to get a generic resilience pipeline from the provider using the specified key.
/// </summary>
/// <typeparam name="TResult">The type of result that the resilience pipeline handles.</typeparam>
/// <param name="key">The key used to identify the resilience pipeline.</param>
/// <param name="pipeline">The output resilience pipeline if found, <see langword="null"/> otherwise.</param>
/// <returns><see langword="true"/> if the pipeline was found, <see langword="false"/> otherwise.</returns>View on GitHub (pinned to d0e46bdb1e)
Solutions
- Register a generic builder/pipeline for the exact TResult: registry.TryAddPipeline<TResult>(key, ...) or TryAddBuilder<TResult>(...).
- If the pipeline is genuinely type-agnostic, resolve the non-generic GetPipeline(key) and wrap with .AsPipeline<TResult>() explicitly.
- Confirm the TResult used at resolution matches the one used at registration, including namespace.
Example fix
// before
registry.TryAddPipeline("api", b => b.AddRetry(new()));
var p = provider.GetPipeline<HttpResponseMessage>("api"); // throws
// after
registry.TryAddPipeline<HttpResponseMessage>("api", b => b.AddRetry(new RetryStrategyOptions<HttpResponseMessage>()));
var p = provider.GetPipeline<HttpResponseMessage>("api"); Defensive patterns
Strategy: validation
Validate before calling
if (provider.TryGetPipeline<TResult>(key, out var pipeline)) {
// use pipeline
} else {
// register the generic pipeline/builder for TResult, or fall back
} Try / catch
try { var p = provider.GetPipeline<TResult>(key); }
catch (KeyNotFoundException ex) when (ex.Message.Contains(typeof(TResult).Name)) {
// register generic builder for TResult or use non-generic pipeline
} Prevention
- Register generic pipelines with the exact TResult you will resolve.
- Keep TResult consistent (same namespace/assembly) between registration and resolution.
- Use TryGetPipeline<TResult> to guard against optional keys.
When it happens
Trigger: Calling provider.GetPipeline<string>(key) when only a non-generic pipeline was registered under key, or when only a different TResult was registered. Also when the generic builder was never added.
Common situations: Registering a builder as non-generic but resolving as generic; TResult mismatch (e.g. registered HttpResponseMessage but resolving as object); assuming generic resolution falls back to non-generic.
Related errors
- Unable to find a resilience pipeline associated with the key
- This instance of 'CircuitBreakerStateProvider' is already in
- No predicates were configured. There must be at least one pr
- The resilience pipeline registry has been disposed and canno
- Disposing this resilience pipeline is not allowed because it
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/0d7906ba281d89d0.
Report an issue: GitHub.