{"record":{"id":"6194634021695d1e","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-oncachemiss","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'onCacheMiss')","messagePattern":"Value cannot be null\\. \\(Parameter 'onCacheMiss'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/Caching/AsyncCacheTResultSyntax.cs","lineNumber":1001,"sourceCode":"\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)\n        {\n            throw new ArgumentNullException(nameof(onCachePut));\n        }\n\n        return new AsyncCachePolicy<TResult>(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError);\n    }\n\n    private static void EmptyCallback(Context context, string key)\n    {\n        // No-op\n    }\n}\n","sourceCodeStart":983,"sourceCodeEnd":1017,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/Caching/AsyncCacheTResultSyntax.cs#L983-L1017","documentation":"Thrown by the terminal CacheAsync<TResult>(...) overload when onCacheMiss is null. The miss callback is mandatory in this verbose overload; a null would NPE at miss time, so it is rejected at construction. Earlier guards (provider, TTL, key, onCacheGet) run before it.","triggerScenarios":"Calling the full overload with null for the onCacheMiss Action<Context,string>.","commonSituations":"Assuming the callback is optional; refactor omitted the assignment; test placeholder left null.","solutions":["Pass a non-null Action<Context,string> (a no-op is acceptable).","Use a simpler overload that injects EmptyCallback if you do not track misses.","Null-check before the call."],"exampleFix":"// before\nvar policy = Policy.CacheAsync<string>(provider, ttlStrategy, keyFunc, onGet, null, onPut, null, null);\n// after\nAction<Context, string> noop = (_, _) => { };\nvar policy = Policy.CacheAsync<string>(provider, ttlStrategy, keyFunc, onGet, noop, onPut, null, null);","handlingStrategy":"validation","validationCode":"Action<Context, string> onMiss = onCacheMiss ?? ((_, _) => { });\nvar policy = Policy.CacheAsync<TResult>(provider, ttlStrategy, keyFunc, onGet, onMiss, onPut, null, null);","typeGuard":"static bool HasCallback(Action<Context, string>? a) => a is not null;","tryCatchPattern":"try { var p = Policy.CacheAsync<R>(provider, ttl, keyFunc, onGet, onMiss, onPut, null, null); }\ncatch (ArgumentNullException ex) when (ex.ParamName == \"onCacheMiss\") { /* supply a no-op callback */ }","preventionTips":["Coalesce the miss callback to a no-op.","Prefer simpler overloads that default callbacks.","Enable nullable reference types."],"tags":["caching","argumentnullexception","null-argument","polly-v7","cache-callback"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}