App-vNext/Polly · error · ArgumentNullException
Value cannot be null. (Parameter 'onCacheGet')
Error message
Value cannot be null. (Parameter 'onCacheGet')
What it means
Thrown by the terminal CacheAsync<TResult>(...) overload when onCacheGet is null. This overload requires explicit lifecycle callbacks (they are not optional here); a null onCacheGet would cause a NullReferenceException at cache-hit time, so the guard rejects it at construction. Provider, TTL, and key-strategy guards run before it.
Source
Thrown at src/Polly/Caching/AsyncCacheTResultSyntax.cs:996
{
if (cacheProvider == null)
{
throw new ArgumentNullException(nameof(cacheProvider));
}
if (ttlStrategy == null)
{
throw new ArgumentNullException(nameof(ttlStrategy));
}
if (cacheKeyStrategy == null)
{
throw new ArgumentNullException(nameof(cacheKeyStrategy));
}
if (onCacheGet == null)
{
throw new ArgumentNullException(nameof(onCacheGet));
}
if (onCacheMiss == null)
{
throw new ArgumentNullException(nameof(onCacheMiss));
}
if (onCachePut == null)
{
throw new ArgumentNullException(nameof(onCachePut));
}
return new AsyncCachePolicy<TResult>(cacheProvider, ttlStrategy, cacheKeyStrategy, onCacheGet, onCacheMiss, onCachePut, onCacheGetError, onCachePutError);
}
private static void EmptyCallback(Context context, string key)
{
// No-opView on GitHub (pinned to d0e46bdb1e)
Solutions
- Provide a non-null Action<Context,string> for onCacheGet, even if it is a no-op like (_, _) => { }.
- Prefer the simpler overloads that supply EmptyCallback automatically when you do not need lifecycle hooks.
- Null-check the callbacks at the call site.
Example fix
// before
var policy = Policy.CacheAsync<string>(provider, ttlStrategy, keyFunc, null, onMiss, onPut, null, null);
// after
Action<Context, string> noop = (_, _) => { };
var policy = Policy.CacheAsync<string>(provider, ttlStrategy, keyFunc, noop, onMiss, onPut, null, null); Defensive patterns
Strategy: validation
Validate before calling
Action<Context, string> onGet = onCacheGet ?? ((_, _) => { });
var policy = Policy.CacheAsync<TResult>(provider, ttlStrategy, keyFunc, onGet, onMiss, onPut, null, null); Type guard
static bool HasCallback(Action<Context, string>? a) => a is not null;
Try / catch
try { var p = Policy.CacheAsync<R>(provider, ttl, keyFunc, onGet, onMiss, onPut, null, null); }
catch (ArgumentNullException ex) when (ex.ParamName == "onCacheGet") { /* supply a no-op callback */ } Prevention
- Coalesce each callback to a no-op when not needed.
- Prefer the simpler overloads that inject EmptyCallback.
- Enable nullable reference types to distinguish optional vs required callbacks.
When it happens
Trigger: Calling the full overload with null for the onCacheGet Action<Context,string>, or passing a callbacks object whose onCacheGet field is null.
Common situations: Developer assumed the callbacks were optional (they are in some overloads via EmptyCallback, but not when you call the full overload directly); refactor removed the callback assignment; test code passed null placeholders.
Related errors
- Value cannot be null. (Parameter 'onCacheMiss')
- Value cannot be null. (Parameter 'onCachePut')
- Value cannot be null. (Parameter 'ttlStrategy')
- Value cannot be null. (Parameter 'wrappedCacheProvider')
- Value cannot be null. (Parameter 'action')
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/3922479d592dc868.
Report an issue: GitHub.