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
- Pass a non-null ISyncCacheProvider (e.g. a registered MemoryCacheProvider, or the provider from CacheProvider.Memory(...)).
- Verify the caching provider package is installed and the provider is resolved from DI before calling Cache(...).
- 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
- Register the cache provider package (e.g. Polly.Caching.MemoryCache) and resolve ISyncCacheProvider from DI.
- Assert the provider is non-null in a startup health check.
- Keep a single composition root that builds the CachePolicy so wiring is verified once.
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
- Value cannot be null. (Parameter 'cacheProvider')
- Value cannot be null. (Parameter 'cacheKeyStrategy')
- Value cannot be null. (Parameter 'ttlStrategy')
- Value cannot be null. (Parameter 'onCacheGet')
- Value cannot be null. (Parameter 'onCacheMiss')
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/3d3f72a4097e282a.
Report an issue: GitHub.