{"record":{"id":"8e9b64c9e4dfac71","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-cachekeystrategy-8e9b64","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'cacheKeyStrategy')","messagePattern":"Value cannot be null\\. \\(Parameter 'cacheKeyStrategy'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/CacheSyntax.cs","lineNumber":56,"sourceCode":"    /// 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    /// <param name=\"cacheProvider\">The cache provider.</param>\n    /// <param name=\"ttl\">Duration (ttl) for which to cache values.</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=\"cacheKeyStrategy\"/> is <see langword=\"null\"/>.</exception>\n    public static CachePolicy Cache(\n        ISyncCacheProvider cacheProvider,\n        TimeSpan ttl,\n        ICacheKeyStrategy cacheKeyStrategy,\n        Action<Context, string, Exception>? onCacheError = null)\n    {\n        if (cacheKeyStrategy is null)\n        {\n            throw new ArgumentNullException(nameof(cacheKeyStrategy));\n        }\n\n        return Cache(cacheProvider, new RelativeTtl(ttl), cacheKeyStrategy.GetCacheKey, onCacheError);\n    }\n\n    /// <summary>\n    /// <para>Builds a <see cref=\"Policy\"/> that will function like a result cache for delegate executions returning a result.</para>\n    /// <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\"/>.\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    /// <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>","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/CacheSyntax.cs#L38-L74","documentation":"Thrown at policy-construction time by the legacy Polly v7 CachePolicy factory Policy.Cache(ISyncCacheProvider, TimeSpan, ICacheKeyStrategy, ...). The overload that takes a custom ICacheKeyStrategy requires it to be non-null because the policy derives every cache key from cacheKeyStrategy.GetCacheKey. Polly fails fast with ArgumentNullException rather than throwing a NullReferenceException later when a delegate executes.","triggerScenarios":"Calling Policy.Cache(cacheProvider, ttl, (ICacheKeyStrategy)null) on the overload whose third parameter is ICacheKeyStrategy. A null reference (uninitialized field, a DI-resolved service that came back null, or a conditional factory that returned null) reaches that argument.","commonSituations":"DI container failed to register or inject the ICacheKeyStrategy; a custom key-strategy property is declared but never assigned; an overload-resolution mistake where you meant to pass a Func<Context,string> but the compiler bound to the ICacheKeyStrategy overload and you passed null.","solutions":["Pass a non-null ICacheKeyStrategy instance to the overload.","If you want default key derivation from Context.OperationKey, use the simpler overload Policy.Cache(cacheProvider, ttl) which supplies DefaultCacheKeyStrategy.Instance for you.","Fix the DI registration / factory so the strategy is never null before the call."],"exampleFix":"// before\nPolicy.Cache(provider, ttl, (ICacheKeyStrategy)null);\n// after\nPolicy.Cache(provider, ttl); // uses DefaultCacheKeyStrategy (Context.OperationKey)","handlingStrategy":"validation","validationCode":"if (cacheKeyStrategy is null) throw new InvalidOperationException(\"cacheKeyStrategy must be configured before building the cache policy.\");\nvar policy = Policy.Cache(cacheProvider, ttl, cacheKeyStrategy);","typeGuard":"static bool IsKeyStrategyValid(Polly.Caching.ICacheKeyStrategy? s) => s is not null;","tryCatchPattern":null,"preventionTips":["Prefer the simpler Policy.Cache(provider, ttl) overload unless you need a custom key strategy.","Resolve the ICacheKeyStrategy from DI at composition time so a missing registration fails loudly during startup.","Use a unit test that builds the policy with realistic arguments to catch null wiring."],"tags":["polly","caching","legacy-v7","argument-null","cache-key-strategy"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}