App-vNext/Polly · error · ArgumentNullException
Value cannot be null.
Error message
Value cannot be null.
What it means
Thrown as ArgumentNullException(nameof(action)) from the non-generic AsyncCachePolicy.ImplementationAsync (the void-returning overload at line 41–54). This overload is a pass-through/NOOP for void executions through the cache policy — it does not actually cache anything, it just validates and invokes the action directly. The null guard at line 47–50 fires before invocation.
Source
Thrown at src/Polly/Caching/AsyncCachePolicy.cs:49
_cacheKeyStrategy = cacheKeyStrategy;
_onCacheGet = onCacheGet;
_onCachePut = onCachePut;
_onCacheMiss = onCacheMiss;
_onCacheGetError = onCacheGetError;
_onCachePutError = onCachePutError;
}
/// <inheritdoc/>
protected override Task ImplementationAsync(
Func<Context, CancellationToken, Task> action,
Context context,
CancellationToken cancellationToken,
bool continueOnCapturedContext)
{
if (action is null)
{
throw new ArgumentNullException(nameof(action));
}
// Pass-through/NOOP policy action, for void-returning executions through the cache policy.
return action(context, cancellationToken);
}
/// <inheritdoc/>
[DebuggerStepThrough]
protected override Task<TResult> ImplementationAsync<TResult>(
Func<Context, CancellationToken, Task<TResult>> action,
Context context,
CancellationToken cancellationToken,
bool continueOnCapturedContext)
{
if (action is null)
{
throw new ArgumentNullException(nameof(action));
}View on GitHub (pinned to d0e46bdb1e)
Solutions
- Ensure the async delegate passed to ExecuteAsync is non-null
- Guard the call site with a null check before invoking
- Use nullable reference types to surface null delegate issues at compile time
Example fix
// before
Func<CancellationToken, Task> doWork = GetWorkAsync(); // may be null
await cachePolicy.ExecuteAsync(doWork); // ArgumentNullException
// after
Func<CancellationToken, Task> doWork = GetWorkAsync();
if (doWork is not null)
{
await cachePolicy.ExecuteAsync(doWork);
} Defensive patterns
Strategy: validation
Validate before calling
if (action is null)
{
throw new InvalidOperationException("Async action must be provided.");
}
await cachePolicy.ExecuteAsync(action); Type guard
public static bool IsExecutableAsyncDelegate(Func<CancellationToken, Task> action) => action is not null;
Prevention
- Enable nullable reference types to surface null delegates at compile time
- Use GetRequiredService for delegate sources from DI
- Avoid conditional delegate assignment without a fallback
When it happens
Trigger: Calling policy.ExecuteAsync(null) on an AsyncCachePolicy where the delegate returns Task (void) rather than Task<TResult>. The pass-through ImplementationAsync at line 41 catches the null action before any cache interaction.
Common situations: Passing a null async delegate to a cache policy's fire-and-forget execution path. Refactoring that moved the delegate construction to a conditional path that returns null. Misunderstanding that void-returning cache executions are pass-through and not cached.
Related errors
- Value cannot be null.
- Value cannot be null.
- Value must be greater than zero.
- Value must be less than or equal to one.
- Value must be equal to or greater than {resolutionOfCircuit.
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/487300954a12b947.
Report an issue: GitHub.