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<TResult>.Execute(Func<Context,CancellationToken,TResult>, Context, CancellationToken) when context is null. This is the strongly-typed (result-locked) policy variant; the guard protects the SetPolicyContext/RestorePolicyContext pair that stamps policy keys onto the context.

Source

Thrown at src/Polly/Policy.TResult.ExecuteOverloads.cs:72

    /// <returns>The value returned by the action.</returns>
    /// <exception cref="ArgumentNullException">Thrown when <paramref name="contextData"/> is <see langword="null"/>.</exception>
    [DebuggerStepThrough]
    public TResult Execute(Func<Context, CancellationToken, TResult> action, IDictionary<string, object> contextData, CancellationToken cancellationToken) =>
        Execute(action, new Context(contextData), cancellationToken);

    /// <summary>
    /// Executes the specified action within the policy and returns the result.
    /// </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>
    /// <returns>The value returned by the action.</returns>
    [DebuggerStepThrough]
    public TResult Execute(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

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

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

    #endregion

    #region ExecuteAndCapture overloads

View on GitHub (pinned to d0e46bdb1e)

Solutions

  1. Pass a real Context: typedPolicy.Execute(func, new Context(), ct).
  2. Default optional parameters: Context context = null is invalid; use Context context = new().
  3. Add a precondition null check at the call site.
  4. Enable NRTs so the compiler rejects Context? being passed to Context parameters.

Example fix

// before
var r = typedPolicy.Execute(func, null, ct);

// after
var r = typedPolicy.Execute(func, new Context(), ct);
Defensive patterns

Strategy: validation

Validate before calling

Context ctx = providedContext ?? new Context();
var r = typedPolicy.Execute(func, ctx, ct);

Type guard

static bool IsContext(object o) => o is Context;

Prevention

When it happens

Trigger: Calling typedPolicy.Execute(func, null, cancellationToken) on a Policy<TResult> instance with a null Context reference.

Common situations: Migrating from a generic Policy to a Policy<TResult> and forgetting that the Context overload still requires a value; forwarding an optional Context parameter without defaulting; reflection-driven test harnesses.

Related errors


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