App-vNext/Polly · error · ArgumentNullException
Value cannot be null. (Parameter 'action')
Error message
Value cannot be null. (Parameter 'action')
What it means
Thrown by AsyncRateLimitPolicy.ImplementationAsync<TResult> when the action delegate is null. This is the factory-less rate limit policy (no retryAfterFactory); it guards the delegate before delegating to AsyncRateLimitEngine, consistent with all Polly strategy implementations.
Source
Thrown at src/Polly/RateLimit/AsyncRateLimitPolicy.cs:24
/// </summary>
public class AsyncRateLimitPolicy : AsyncPolicy, IRateLimitPolicy
{
private readonly IRateLimiter _rateLimiter;
internal AsyncRateLimitPolicy(IRateLimiter rateLimiter) =>
_rateLimiter = rateLimiter;
/// <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 AsyncRateLimitEngine.ImplementationAsync(
_rateLimiter,
null,
action,
context,
continueOnCapturedContext,
cancellationToken);
}
}
/// <summary>
/// A rate-limit policy that can be applied to asynchronous delegates returning a value of type <typeparamref name="TResult"/>.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
public class AsyncRateLimitPolicy<TResult> : AsyncPolicy<TResult>, IRateLimitPolicy<TResult>
{View on GitHub (pinned to d0e46bdb1e)
Solutions
- Always pass a non-null Func<Context, CancellationToken, Task<TResult>> to ExecuteAsync.
- If the delegate is optional in your API, branch around the call rather than passing null.
- Add a precondition null check at the call site.
- Enable nullable reference types to surface nullable delegates at compile time.
Example fix
// before await rlPolicy.ExecuteAsync<int>(null, context, ct); // after await rlPolicy.ExecuteAsync<int>((ctx, ct) => Task.FromResult(42), context, ct);
Defensive patterns
Strategy: validation
Validate before calling
if (action is null) throw new ArgumentNullException(nameof(action)); await rlPolicy.ExecuteAsync(action ?? throw new ArgumentNullException(nameof(action)), context, ct);
Type guard
static bool IsAsyncFunc<T>(Delegate d) => d is Func<Context, CancellationToken, Task<T>>;
Prevention
- Never pass default(Func<...>) to ExecuteAsync.
- Branch around optional delegates instead of forwarding null.
- Enable NRTs to catch nullable async delegates.
When it happens
Trigger: Invoking ImplementationAsync with a null action on an AsyncRateLimitPolicy instance. Normally reached via internal Policy.ExecuteAsync plumbing when a null delegate reaches the strategy, or via direct subclass/reflection use.
Common situations: A wrapper that conditionally passes a delegate and forwards null; a refactor that introduced a nullable action parameter; reflection-driven invocation in tests.
Related errors
- Value cannot be null. (Parameter 'action')
- Value cannot be null. (Parameter 'context')
- Value cannot be null. (Parameter 'context')
- numberOfExecutions per timespan must be an integer greater t
- perTimeSpan must be a positive timespan.
AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13).
Data as JSON: /api/errors/b402ea182697eb24.
Report an issue: GitHub.