{"record":{"id":"057c499d0eb7028d","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-ttlstrategy","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/AsyncCacheTResultSyntax.cs","lineNumber":986,"sourceCode":"    /// <exception cref=\"ArgumentNullException\">Thrown when <paramref name=\"onCachePut\"/> is <see langword=\"null\"/>.</exception>\n    public static AsyncCachePolicy<TResult> CacheAsync<TResult>(\n        IAsyncCacheProvider<TResult> cacheProvider,\n        ITtlStrategy<TResult> ttlStrategy,\n        Func<Context, string> cacheKeyStrategy,\n        Action<Context, string> onCacheGet,\n        Action<Context, string> onCacheMiss,\n        Action<Context, string> onCachePut,\n        Action<Context, string, Exception>? onCacheGetError,\n        Action<Context, string, Exception>? onCachePutError)\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        if (onCacheGet == null)\n        {\n            throw new ArgumentNullException(nameof(onCacheGet));\n        }\n\n        if (onCacheMiss == null)\n        {\n            throw new ArgumentNullException(nameof(onCacheMiss));\n        }\n\n        if (onCachePut == null)","sourceCodeStart":968,"sourceCodeEnd":1004,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/AsyncCacheTResultSyntax.cs#L968-L1004","documentation":"Thrown by the terminal CacheAsync<TResult>(...) overload when ttlStrategy is null. The TTL strategy decides how long cached values live; a null strategy would leave expiration undefined, so construction is rejected. The provider guard runs first, so this only fires when the provider is valid but the TTL is null.","triggerScenarios":"Calling the full overload (or a public overload that funnels here) with a null ITtlStrategy<TResult>, e.g. passing null where a RelativeTtl or ContextualTtl should be.","commonSituations":"The TTL strategy field was never assigned; a config-driven TTL factory returned null when the config section was absent; refactor swapped in an overload that no longer wraps TimeSpan into RelativeTtl.","solutions":["Pass a concrete ITtlStrategy<TResult> such as new RelativeTtl(TimeSpan.FromMinutes(5)).","If you only need a fixed TTL, prefer the TimeSpan-based overload which constructs RelativeTtl for you.","Null-check the strategy at the call site."],"exampleFix":"// before\nvar policy = Policy.CacheAsync<string>(provider, (ITtlStrategy<string>)null, keyFunc, onGet, onMiss, onPut, null, null);\n// after\nvar policy = Policy.CacheAsync<string>(provider, new RelativeTtl(TimeSpan.FromMinutes(5)).For<string>(), keyFunc, onGet, onMiss, onPut, null, null);","handlingStrategy":"validation","validationCode":"var ttl = ttlStrategy ?? new RelativeTtl(TimeSpan.FromMinutes(5));\nvar policy = Policy.CacheAsync<TResult>(provider, ttl.For<TResult>(), keyFunc, onGet, onMiss, onPut, null, null);","typeGuard":"static bool HasTtl<T>(ITtlStrategy<T>? s) => s is not null;","tryCatchPattern":"try { var p = Policy.CacheAsync<R>(provider, ttl, keyFunc, onGet, onMiss, onPut, null, null); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"ttlStrategy\") { /* default the TTL or fail */ }","preventionTips":["Default to RelativeTtl in your builder when no custom TTL is configured.","Prefer the TimeSpan overload for fixed TTLs.","Validate config sections that drive TTL construction."],"tags":["caching","argumentnullexception","null-argument","polly-v7","ttl-strategy"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}