{"record":{"id":"bd2fccdc4cefebe3","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-cacheprovider","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'cacheProvider')","messagePattern":"Value cannot be null\\. \\(Parameter 'cacheProvider'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/AsyncCacheTResultSyntax.cs","lineNumber":161,"sourceCode":"    /// <para>Builds an <see cref=\"AsyncPolicy{TResult}\" /> that will function like a result cache for delegate executions returning a <typeparamref name=\"TResult\"/>.</para>\n    /// <para>Before executing a delegate, 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\"/>.\n    /// 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.\n    /// </para>\n    /// </summary>\n    /// <typeparam name=\"TResult\">The type of the result.</typeparam>\n    /// <param name=\"cacheProvider\">The cache provider.</param>\n    /// <param name=\"ttlStrategy\">A strategy for specifying ttl for values to be cached.</param>\n    /// <param name=\"cacheKeyStrategy\">The cache key strategy.</param>\n    /// <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>\n    /// <returns>The policy instance.</returns>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"cacheProvider\"/> is <see langword=\"null\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"ttlStrategy\"/> is <see langword=\"null\"/>.</exception>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"cacheKeyStrategy\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncCachePolicy<TResult> CacheAsync<TResult>(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func<Context, string> cacheKeyStrategy, Action<Context, string, Exception>? onCacheError = null)\n    {\n        if (cacheProvider == null)\n        {\n            throw new ArgumentNullException(nameof(cacheProvider));\n        }\n\n        return CacheAsync(cacheProvider.AsyncFor<TResult>(), ttlStrategy, cacheKeyStrategy, onCacheError);\n    }\n\n    /// <summary>\n    /// <para>Builds an <see cref=\"AsyncPolicy{TResult}\" /> that will function like a result cache for delegate executions returning a <typeparamref name=\"TResult\"/>.</para>\n    /// <para>Before executing a delegate, checks whether the <paramref name=\"cacheProvider\" /> holds a value for the cache key.\n    /// 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.\n    /// </para>\n    /// </summary>\n    /// <typeparam name=\"TResult\">The type of the result.</typeparam>\n    /// <param name=\"cacheProvider\">The cache provider.</param>\n    /// <param name=\"ttl\">Duration (ttl) for which to cache values.</param>\n    /// <param name=\"onCacheGet\">Delegate to call on a cache hit, when value is returned from cache.</param>\n    /// <param name=\"onCacheMiss\">Delegate to call on a cache miss.</param>\n    /// <param name=\"onCachePut\">Delegate to call on cache put.</param>\n    /// <param name=\"onCacheGetError\">Delegate to call if an exception is thrown when attempting to get a value from the cache, passing the execution context, the cache key, and the exception.</param>","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/AsyncCacheTResultSyntax.cs#L143-L179","documentation":"Thrown by CacheAsync<TResult>(IAsyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, Func<Context,string> cacheKeyStrategy, ...) (AsyncCacheTResultSyntax.cs:157) when cacheProvider is null. This is the terminal typed-result Func-key convenience overload; it validates only cacheProvider here and forwards to the 8-parameter overload for the rest.","triggerScenarios":"Calling Policy.CacheAsync<TResult>(null, ttlStrategy, keyFunc, onCacheError).","commonSituations":"Provider injected as null; migration to distributed cache that failed to construct.","solutions":["Pass a non-null IAsyncCacheProvider.","Register the cache provider as a DI singleton and assert non-null at startup."],"exampleFix":"// before\nPolicy.CacheAsync<MyResult>(null, ttlStrategy, ctx => ctx.OperationKey);\n\n// after\nPolicy.CacheAsync<MyResult>(cacheProvider, ttlStrategy, ctx => ctx.OperationKey);","handlingStrategy":"validation","validationCode":"ArgumentNullException.ThrowIfNull(cacheProvider);\nvar policy = Policy.CacheAsync<TResult>(cacheProvider, ttlStrategy, keyFunc, onCacheError);","typeGuard":"static bool IsCacheProviderValid(IAsyncCacheProvider? p) => p is not null;","tryCatchPattern":null,"preventionTips":["Register the cache provider in DI and resolve it explicitly at startup.","Keep provider construction eager, not lazy.","Enable nullable reference types so a null provider is a compile-time warning."],"tags":["polly","caching","argumentnullexception","cache-provider","typed-result","csharp"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}