{"record":{"id":"60fbe8ac1331d4bc","repo":"App-vNext/Polly","slug":"value-cannot-be-null-60fbe8","errorCode":null,"errorMessage":"Value cannot be null.","messagePattern":"Value cannot be null\\.","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/AsyncCacheTResultSyntax.cs","lineNumber":22,"sourceCode":"public partial class Policy\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 specified by <see cref=\"Context.OperationKey\"/>.\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=\"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    public static AsyncCachePolicy<TResult> CacheAsync<TResult>(IAsyncCacheProvider cacheProvider, TimeSpan ttl, 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>(), new RelativeTtl(ttl), DefaultCacheKeyStrategy.Instance.GetCacheKey, 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 specified by <see cref=\"Context.OperationKey\"/>.\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=\"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>","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/AsyncCacheTResultSyntax.cs#L4-L40","documentation":"Thrown by CacheAsync<TResult>(IAsyncCacheProvider cacheProvider, TimeSpan ttl, ...) (AsyncCacheTResultSyntax.cs:18) when cacheProvider is null. This is the typed-result convenience overload that wraps the provider via AsyncFor<TResult>() and builds a RelativeTtl; a null provider cannot be typed and would NRE, so it is rejected here.","triggerScenarios":"Calling Policy.CacheAsync<TResult>(null, TimeSpan.FromMinutes(5), onCacheError) — the IAsyncCacheProvider (1st positional) is null.","commonSituations":"DI did not register the cache provider; passing a field initialized after policy construction; provider creation threw and the variable stayed null.","solutions":["Pass a non-null IAsyncCacheProvider, e.g. new MemoryCacheProvider(MemoryCache.Default).","Confirm the DI registration and lifetime of the injected provider.","Construct the provider eagerly before building the policy."],"exampleFix":"// before\nvar policy = Policy.CacheAsync<MyResult>(null, TimeSpan.FromMinutes(5));\n\n// after\nvar policy = Policy.CacheAsync<MyResult>(new MemoryCacheProvider(MemoryCache.Default), TimeSpan.FromMinutes(5));","handlingStrategy":"validation","validationCode":"ArgumentNullException.ThrowIfNull(cacheProvider);\nvar policy = Policy.CacheAsync<TResult>(cacheProvider, TimeSpan.FromMinutes(5), onCacheError);","typeGuard":"static bool IsCacheProviderValid(IAsyncCacheProvider? p) => p is not null;","tryCatchPattern":null,"preventionTips":["Register the IAsyncCacheProvider in DI and resolve it before building typed cache policies.","Enable nullable reference types to catch unassigned providers at compile time.","Construct the provider eagerly so it is never lazily null."],"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"}