{"record":{"id":"2f096bf505b20f14","repo":"App-vNext/Polly","slug":"value-cannot-be-null-parameter-action-2f096b","errorCode":null,"errorMessage":"Value cannot be null. (Parameter 'action')","messagePattern":"Value cannot be null\\. \\(Parameter 'action'\\)","errorType":"exception","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"src/Polly/NoOp/AsyncNoOpPolicy.cs","lineNumber":20,"sourceCode":"namespace Polly.NoOp;\n\n/// <summary>\n/// A noop policy that can be applied to asynchronous delegates.\n/// </summary>\npublic class AsyncNoOpPolicy : AsyncPolicy, INoOpPolicy\n{\n    internal AsyncNoOpPolicy()\n    {\n    }\n\n    /// <inheritdoc/>\n    [DebuggerStepThrough]\n    protected override Task<TResult> ImplementationAsync<TResult>(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken,\n        bool continueOnCapturedContext)\n    {\n        if (action is null)\n        {\n            throw new ArgumentNullException(nameof(action));\n        }\n\n        return NoOpEngine.ImplementationAsync(action, context, cancellationToken);\n    }\n}\n\n/// <summary>\n/// A noop policy that can be applied to asynchronous delegates returning a value of type <typeparamref name=\"TResult\"/>.\n/// </summary>\n/// <typeparam name=\"TResult\">The type of the result.</typeparam>\npublic class AsyncNoOpPolicy<TResult> : AsyncPolicy<TResult>, INoOpPolicy<TResult>\n{\n    internal AsyncNoOpPolicy()\n    {\n    }\n\n    /// <inheritdoc/>\n    [DebuggerStepThrough]","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/App-vNext/Polly/blob/d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac/src/Polly/NoOp/AsyncNoOpPolicy.cs#L2-L38","documentation":"ArgumentNullException thrown by AsyncNoOpPolicy (non-generic).ImplementationAsync when the action delegate is null. NoOp passes the delegate straight through to NoOpEngine, so a null action cannot be invoked. The guard fires when the policy's Execute path is entered with a null func.","triggerScenarios":"Calling policy.ExecuteAsync(null) or passing a null Func<Context, CancellationToken, Task<TResult>> into an AsyncNoOpPolicy obtained via Policy.NoOpAsync().","commonSituations":"A null delegate resolved from DI/optional config; refactor that changed the delegate signature leaving a null reference; tests asserting no-op behavior but forgetting to supply a delegate.","solutions":["Pass a non-null action delegate to ExecuteAsync.","Guard the delegate before calling: if (action is not null) await policy.ExecuteAsync(action).","Check DI registrations resolve a real delegate, not null."],"exampleFix":"// before\nFunc<CancellationToken, Task<int>> action = GetAction(); // may be null\nvar result = await noOpPolicy.ExecuteAsync(action, ct);\n\n// after\nvar action = GetAction() ?? (_ => Task.FromResult(0));\nvar result = await noOpPolicy.ExecuteAsync(action, ct);","handlingStrategy":"validation","validationCode":"if (action is null) throw new ArgumentNullException(nameof(action));\nawait Policy.NoOpAsync().ExecuteAsync(action, ctx, ct);","typeGuard":"static Func<Context, CancellationToken, Task<T>> EnsureAction<T>(Func<Context, CancellationToken, Task<T>> a) => a ?? ((_, _) => Task.FromResult<T>(default));","tryCatchPattern":"try { await noOpPolicy.ExecuteAsync(action, ct); } catch (ArgumentNullException ex) when (ex.ParamName == \"action\") { /* supply delegate */ throw; }","preventionTips":["Validate delegates from DI/factories are non-null before executing.","Coalesce with a default-returning delegate when null is plausible.","Add a unit test executing NoOp with a real delegate."],"tags":["noop","argument-validation","null-check","async","csharp","legacy-api"],"backgroundTag":null,"analyzedSha":"d0e46bdb1ee11ea50d0e4b6846d2633d6bc09bac","analyzedAt":"2026-08-13T16:36:01.959Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}