App-vNext/Polly · error · InvalidOperationException

Disposing this resilience pipeline is not allowed because it

Error message

Disposing this resilience pipeline is not allowed because it is owned by the pipeline registry.

What it means

When ComponentDisposeHelper is constructed with DisposeBehavior.Reject, DisposeAsync throws InvalidOperationException. Pipelines resolved from ResiliencePipelineRegistry are given Reject behavior because the registry owns their lifetime; calling Dispose on such a pipeline would double-dispose resources the registry still manages.

Source

Thrown at src/Polly.Core/Utils/Pipeline/ComponentDisposeHelper.cs:50

    private static void ThrowDisposed() => throw new ObjectDisposedException("ResiliencePipeline", "This resilience pipeline has been disposed and cannot be used anymore.");

    public ValueTask ForceDisposeAsync()
    {
        _disposed = true;
        return _component.DisposeAsync();
    }

    private bool EnsureDisposable()
    {
        if (_disposeBehavior == DisposeBehavior.Ignore)
        {
            return false;
        }

        if (_disposeBehavior == DisposeBehavior.Reject)
        {
            throw new InvalidOperationException("Disposing this resilience pipeline is not allowed because it is owned by the pipeline registry.");
        }

        return !_disposed;
    }
}

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Do not dispose pipelines that come from the registry/provider; let the registry manage their lifetime.
  2. If you need a disposable pipeline, build it yourself with new ResiliencePipelineBuilder().AddStrategy(...).Build().
  3. Inject IReadOnlyResiliencePipelineProvider or the pipeline without an owning contract so consumers cannot dispose it.

Example fix

// before
var pipeline = registry.GetPipeline("k");
await pipeline.DisposeAsync(); // throws: owned by registry

// after
var pipeline = registry.GetPipeline("k");
// use freely; do NOT dispose. Dispose the registry instead at app shutdown.
Defensive patterns

Strategy: validation

Try / catch

try { await pipeline.DisposeAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("pipeline registry")) {
    // ignore: registry owns this pipeline; nothing to do
}

Prevention

When it happens

Trigger: Calling .Dispose()/.DisposeAsync() on a ResiliencePipeline obtained via registry.GetPipeline(...) or the DI ResiliencePipelineProvider, since those set Reject behavior.

Common situations: Treating a registry-resolved pipeline like a normally-owned one and wrapping it in 'using'; injecting a pipeline and disposing it in a consumer's Dispose; refactoring from a self-built pipeline (which you may dispose) to a registry-resolved one without removing the dispose call.

Related errors


AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13). Data as JSON: /api/errors/b55b835b1bf9f0da. Report an issue: GitHub.