App-vNext/Polly · error · ArgumentNullException

Value cannot be null. (Parameter 'cacheProvider')

Error message

Value cannot be null. (Parameter 'cacheProvider')

What it means

Thrown at policy-construction time by the legacy Polly v7 overload Policy.Cache(ISyncCacheProvider, ITtlStrategy, ICacheKeyStrategy, ...). The cache provider is the core dependency of a CachePolicy (it actually stores/retrieves cached values), so Polly rejects a null provider immediately with ArgumentNullException. Without it the policy cannot function.

Source

Thrown at src/Polly/Caching/CacheSyntax.cs:80

    /// <summary>
    /// <para>Builds a <see cref="Policy"/> that will function like a result cache for delegate executions returning a result.</para>
    /// <para>Before executing a delegate returning a result, checks whether the <paramref name="cacheProvider"/> holds a value for the cache key determined by applying the <paramref name="cacheKeyStrategy"/> to the execution <see cref="Context"/>.
    /// If the <paramref name="cacheProvider"/> provides a value from cache, returns that value and does not execute the governed delegate.  If the <paramref name="cacheProvider"/> does not provide a value, executes the governed delegate, stores the value with the <paramref name="cacheProvider"/>, then returns the value.
    /// </para>
    /// </summary>
    /// <param name="cacheProvider">The cache provider.</param>
    /// <param name="ttlStrategy">A strategy for specifying ttl for values to be cached.</param>
    /// <param name="cacheKeyStrategy">The cache key strategy.</param>
    /// <param name="onCacheError">Delegate to call if an exception is thrown when attempting to get a value from or put a value into the cache, passing the execution context, the cache key, and the exception.</param>
    /// <returns>The policy instance.</returns>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="cacheProvider"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="ttlStrategy"/> is <see langword="null"/>.</exception>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="cacheKeyStrategy"/> is <see langword="null"/>.</exception>
    public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action<Context, string, Exception>? onCacheError = null)
    {
        if (cacheProvider == null)
        {
            throw new ArgumentNullException(nameof(cacheProvider));
        }

        if (ttlStrategy == null)
        {
            throw new ArgumentNullException(nameof(ttlStrategy));
        }

        if (cacheKeyStrategy == null)
        {
            throw new ArgumentNullException(nameof(cacheKeyStrategy));
        }

        return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, EmptyCallback, EmptyCallback, EmptyCallback, onCacheError, onCacheError);
    }

    /// <summary>
    /// <para>Builds a <see cref="Policy"/> that will function like a result cache for delegate executions returning a result.</para>
    /// <para>Before executing a delegate returning a result, checks whether the <paramref name="cacheProvider" /> holds a value for the cache key determined by applying the <paramref name="cacheKeyStrategy"/> to the execution <see cref="Context"/>.

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Pass a non-null ISyncCacheProvider (e.g. a registered MemoryCacheProvider, or the provider from CacheProvider.Memory(...)).
  2. Verify the caching provider package is installed and the provider is resolved from DI before calling Cache(...).
  3. Use the simpler overload that takes a TimeSpan ttl if you do not have an ITtlStrategy.

Example fix

// before
Policy.Cache(null, new RelativeTtl(ttl), myStrategy);
// after
Policy.Cache(memoryCacheProvider, new RelativeTtl(ttl), myStrategy);
Defensive patterns

Strategy: validation

Validate before calling

if (cacheProvider is null) throw new InvalidOperationException("cacheProvider is not registered.");
var policy = Policy.Cache(cacheProvider, ttlStrategy, cacheKeyStrategy);

Type guard

static bool IsCacheProviderValid(Polly.Caching.ISyncCacheProvider? p) => p is not null;

Prevention

When it happens

Trigger: Calling Policy.Cache(null, ttlStrategy, cacheKeyStrategy, ...) on the ITtlStrategy-based overload, i.e. the ISyncCacheProvider argument is null.

Common situations: The cache provider was never instantiated (e.g. you forgot to wrap a MemoryCache with CacheProvider.Memory/Microsoft.Extensions.Caching.Memory); a DI-injected ISyncCacheProvider resolved to null because the package providing a provider was not referenced; refactoring changed the provider type but not the call site.

Related errors


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