{"record":{"id":"0368dca8c707e0a9","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-ttlstrategy-0368dc","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'ttlStrategy')","messagePattern":"Value cannot be null\\. \\(Parameter 'ttlStrategy'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/CacheSyntax.cs","lineNumber":85,"sourceCode":"    /// </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>\n    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"cacheKeyStrategy\"/> is <see langword=\"null\"/>.</exception>\n    public static CachePolicy Cache(ISyncCacheProvider cacheProvider, ITtlStrategy ttlStrategy, ICacheKeyStrategy cacheKeyStrategy, Action<Context, string, Exception>? onCacheError = null)\n    {\n        if (cacheProvider == null)\n        {\n            throw new ArgumentNullException(nameof(cacheProvider));\n        }\n\n        if (ttlStrategy == null)\n        {\n            throw new ArgumentNullException(nameof(ttlStrategy));\n        }\n\n        if (cacheKeyStrategy == null)\n        {\n            throw new ArgumentNullException(nameof(cacheKeyStrategy));\n        }\n\n        return Cache(cacheProvider, ttlStrategy, cacheKeyStrategy.GetCacheKey, EmptyCallback, EmptyCallback, EmptyCallback, onCacheError, 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=\"ttl\">Duration (ttl) for which to cache values.</param>","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/CacheSyntax.cs#L67-L103","documentation":"Thrown at policy-construction time by the legacy Polly v7 overload Policy.Cache(ISyncCacheProvider, ITtlStrategy, ICacheKeyStrategy, ...). The ITtlStrategy decides how long each cached item is valid; a null strategy would cause a NullReferenceException on every cache miss, so Polly validates it up front with ArgumentNullException.","triggerScenarios":"Calling Policy.Cache(cacheProvider, null, cacheKeyStrategy, ...) — the ITtlStrategy argument is null.","commonSituations":"You removed a TTL strategy but left the call site; a custom ITtlStrategy factory returned null; you intended the TimeSpan overload (which builds a RelativeTtl internally) but called the ITtlStrategy overload with null.","solutions":["Pass a non-null ITtlStrategy such as new RelativeTtl(ttl) or new SlidingTtl(ttl).","If you only have a fixed duration, switch to the overload Policy.Cache(cacheProvider, TimeSpan ttl, cacheKeyStrategy) which wraps the TimeSpan in a RelativeTtl for you."],"exampleFix":"// before\nPolicy.Cache(provider, null, myStrategy);\n// after\nPolicy.Cache(provider, new RelativeTtl(TimeSpan.FromMinutes(5)), myStrategy);","handlingStrategy":"validation","validationCode":"if (ttlStrategy is null) throw new InvalidOperationException(\"ttlStrategy must be provided.\");\nvar policy = Policy.Cache(cacheProvider, ttlStrategy, cacheKeyStrategy);","typeGuard":"static bool IsTtlStrategyValid(Polly.Caching.ITtlStrategy? s) => s is not null;","tryCatchPattern":null,"preventionTips":["Use the TimeSpan overload when you only need a fixed TTL — it builds the RelativeTtl for you.","Construct ITtlStrategy in a factory that never returns null.","Validate the strategy in a composition-root test."],"tags":["polly","caching","legacy-v7","argument-null","ttl-strategy"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}