App-vNext/Polly · error · ArgumentNullException

Value cannot be null. (Parameter 'context')

Error message

Value cannot be null. (Parameter 'context')

What it means

Thrown by Policy.Execute(Action<Context,CancellationToken>, Context, CancellationToken) when the context argument is null. The context carries per-execution metadata and policy wrap keys through the pipeline, so Polly refuses to run without it. The guard sits before SetPolicyContext so that context bookkeeping never dereferences null.

Source

Thrown at src/Polly/Policy.ExecuteOverloads.cs:64

    /// <param name="contextData">Arbitrary data that is passed to the exception policy.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="contextData"/> is <see langword="null"/>.</exception>
    [DebuggerStepThrough]
    public void Execute(Action<Context, CancellationToken> action, IDictionary<string, object> contextData, CancellationToken cancellationToken) =>
        Execute(action, new Context(contextData), cancellationToken);

    /// <summary>
    /// Executes the specified action within the policy.
    /// </summary>
    /// <param name="action">The action to perform.</param>
    /// <param name="context">Context data that is passed to the exception policy.</param>
    /// <param name="cancellationToken">The cancellation token.</param>
    [DebuggerStepThrough]
    public void Execute(Action<Context, CancellationToken> action, Context context, CancellationToken cancellationToken)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        SetPolicyContext(context, out string priorPolicyWrapKey, out string priorPolicyKey);

        try
        {
            Implementation(action, context, cancellationToken);
        }
        finally
        {
            RestorePolicyContext(context, priorPolicyWrapKey, priorPolicyKey);
        }
    }

    #region Overloads method-generic in TResult

    /// <summary>
    /// Executes the specified action within the policy and returns the Result.

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Construct and pass a new Context() (or Context with a correlation key) instead of null: policy.Execute(action, new Context(), ct).
  2. If the context arrives from an optional parameter, default it to a fresh Context in the method signature.
  3. Add a null check on the context at the call site before invoking Execute.
  4. Enable nullable reference types so the compiler flags nullable Context arguments at the call site.

Example fix

// before
Context ctx = GetContextMaybeNull();
policy.Execute(action, ctx, ct);

// after
Context ctx = GetContextMaybeNull() ?? new Context();
policy.Execute(action, ctx, ct);
Defensive patterns

Strategy: validation

Validate before calling

Context ctx = providedContext ?? new Context();
policy.Execute(action, ctx, cancellationToken);

Type guard

static bool IsContext(object o) => o is Context;
// or guard: if (providedContext is not Context) return;

Prevention

When it happens

Trigger: Invoking policy.Execute(action, null, cancellationToken) on a non-generic Policy where the second argument is a null Context reference. Any synchronous Execute overload that requires an explicit Context hits this same guard shape.

Common situations: Passing a Context obtained from a nullable field or optional parameter without checking it; migrating from a context-free Execute overload and forgetting to construct a Context; DI/proxy code that forwards a possibly-null context.

Related errors


AI-assisted analysis of App-vNext/Polly@d0e46bdb1e (2026-08-13). Data as JSON: /api/errors/31b872dc9a2e1dc8. Report an issue: GitHub.