App-vNext/Polly · error · ArgumentNullException
Value cannot be null. (Parameter 'action')
Error message
Value cannot be null. (Parameter 'action')
What it means
Thrown by RateLimitPolicy.Implementation<TResult> (synchronous) when the action delegate is null. This is the factory-less sync rate limit policy; the guard mirrors every other Polly strategy: validate the delegate before invoking RateLimitEngine.
Source
Thrown at src/Polly/RateLimit/RateLimitPolicy.cs:20
namespace Polly.RateLimit;
/// <summary>
/// A rate-limit policy that can be applied to synchronous delegates.
/// </summary>
public class RateLimitPolicy : Policy, IRateLimitPolicy
{
private readonly IRateLimiter _rateLimiter;
internal RateLimitPolicy(IRateLimiter rateLimiter) =>
_rateLimiter = rateLimiter;
/// <inheritdoc/>
[DebuggerStepThrough]
protected override TResult Implementation<TResult>(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
{
if (action is null)
{
throw new ArgumentNullException(nameof(action));
}
return RateLimitEngine.Implementation(_rateLimiter, null, action, context, cancellationToken);
}
}
/// <summary>
/// A rate-limit policy that can be applied to synchronous delegates returning a value of type <typeparamref name="TResult"/>.
/// </summary>
/// <typeparam name="TResult">The type of the result.</typeparam>
public class RateLimitPolicy<TResult> : Policy<TResult>, IRateLimitPolicy<TResult>
{
private readonly IRateLimiter _rateLimiter;
private readonly Func<TimeSpan, Context, TResult>? _retryAfterFactory;
internal RateLimitPolicy(
IRateLimiter rateLimiter,
Func<TimeSpan, Context, TResult>? retryAfterFactory)View on GitHub (pinned to d0e46bdb1e)
Solutions
- Pass a non-null Func<Context, CancellationToken, TResult> to Execute.
- Branch around the call when the delegate is optional rather than passing null.
- Add a precondition null check in your caller.
- Enable nullable reference types to surface nullable delegates at compile time.
Example fix
// before rlPolicy.Execute<int>(null, context, ct); // after rlPolicy.Execute<int>((ctx, ct) => 42, context, ct);
Defensive patterns
Strategy: validation
Validate before calling
if (action is null) throw new ArgumentNullException(nameof(action)); rlPolicy.Execute(action ?? throw new ArgumentNullException(nameof(action)), context, ct);
Type guard
static bool IsFunc<T>(Delegate d) => d is Func<Context, CancellationToken, T>;
Prevention
- Never pass default(Func<...>) to a sync Execute.
- Validate delegates at your wrapper boundary.
- Enable NRTs so nullable delegates surface at compile time.
When it happens
Trigger: Calling Implementation with a null action on a RateLimitPolicy instance. Normally reached through internal Policy.Execute plumbing when a null delegate reaches the strategy, or via direct subclass/reflection.
Common situations: A wrapper that conditionally forwards a delegate and passes null; default(Func<...>) assigned and forwarded; reflection-driven test invocation of the protected member.
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/838abf9b052b3297.
Report an issue: GitHub.