App-vNext/Polly · error · ArgumentNullException
action
Error message
action
What it means
ArgumentNullException (ParamName "action") is thrown by the non-generic AsyncTimeoutPolicy.ImplementationAsync (AsyncTimeoutPolicy.cs:30-33) when the delegate passed for execution is null. This is the protected execution entry point; the null check protects the engine before it dereferences the action to start the task. It indicates the caller handed the policy a null lambda rather than a real operation.
Source
Thrown at src/Polly/Timeout/AsyncTimeoutPolicy.cs:32
TimeoutStrategy timeoutStrategy,
Func<Context, TimeSpan, Task, Exception, Task> onTimeoutAsync)
{
_timeoutProvider = timeoutProvider;
_timeoutStrategy = timeoutStrategy;
_onTimeoutAsync = onTimeoutAsync;
}
/// <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));
}
return AsyncTimeoutEngine.ImplementationAsync(
action,
context,
_timeoutProvider,
_timeoutStrategy,
_onTimeoutAsync,
continueOnCapturedContext,
cancellationToken);
}
}
/// <summary>
/// A timeout policy which can be applied to async delegates.
/// </summary>
/// <typeparam name="TResult">The return type of delegates which may be executed through the policy.</typeparam>
public class AsyncTimeoutPolicy<TResult> : AsyncPolicy<TResult>, ITimeoutPolicy<TResult>View on GitHub (pinned to d0e46bdb1e)
Solutions
- Pass a non-null delegate: policy.ExecuteAsync(ct => DoWorkAsync(ct)).
- Guard the action variable before execution: if (action is null) throw new InvalidOperationException(...).
- Ensure DI registrations for the delegate factory return a real delegate, never null.
Example fix
// before
Func<CancellationToken, Task<string>> action = GetAction(); // returns null
await timeoutPolicy.ExecuteAsync(action);
// after
Func<CancellationToken, Task<string>> action = GetAction()
?? throw new InvalidOperationException("action factory returned null");
await timeoutPolicy.ExecuteAsync(action); Defensive patterns
Strategy: validation
Validate before calling
if (action is null) throw new InvalidOperationException("Execution action must be provided.");
await timeoutPolicy.ExecuteAsync(action); Type guard
static bool IsValidAction<TResult>(Func<Context, CancellationToken, Task<TResult>> action)
=> action is not null; Prevention
- Always pass an inline lambda or a verified non-null delegate to ExecuteAsync; avoid nullable delegate variables.
- Coalesce null with ?? throw new InvalidOperationException(...) at the source so the error is contextual.
- Validate DI-resolved delegate factories in the composition root.
When it happens
Trigger: Calling policy.ExecuteAsync(null) or ExecuteAsync((Func<...>)null) on an AsyncTimeoutPolicy; passing a null Func<Context,CancellationToken,Task<TResult>> directly through the lower-level ImplementationAsync surface.
Common situations: Refactor that extracted the operation into a variable that resolved to null; DI failing to resolve the delegate factory; tests stubbing the action parameter; conditional code paths that forget to assign the action.
Related errors
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/9fff3ca9eeaef3d5.
Report an issue: GitHub.