{"record":{"id":"06f47b67630ccf9c","repo":"dotnet/reactive","slug":"action-value-cannot-be-null-scheduler-simple","errorCode":null,"errorMessage":"action (Value cannot be null)","messagePattern":"action \\(Value cannot be null\\)","errorType":"validation","errorClass":"ArgumentNullException","httpStatus":null,"severity":"error","filePath":"Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Simple.cs","lineNumber":27,"sourceCode":"    public static partial class Scheduler\n    {\n        /// <summary>\n        /// Schedules an action to be executed.\n        /// </summary>\n        /// <param name=\"scheduler\">Scheduler to execute the action on.</param>\n        /// <param name=\"action\">Action to execute.</param>\n        /// <returns>The disposable object used to cancel the scheduled action (best effort).</returns>\n        /// <exception cref=\"ArgumentNullException\"><paramref name=\"scheduler\"/> or <paramref name=\"action\"/> is <c>null</c>.</exception>\n        public static IDisposable Schedule(this IScheduler scheduler, Action action)\n        {\n            if (scheduler == null)\n            {\n                throw new ArgumentNullException(nameof(scheduler));\n            }\n\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action));\n            }\n\n            // Surprisingly, passing the method group of Invoke will create a fresh\n            // delegate each time although it's static, while an anonymous\n            // lambda without the need of a closure will be cached.\n            // Once Roslyn supports caching delegates for method groups,\n            // the anonymous lambda can be replaced by the method group again. Until then,\n            // to avoid the repetition of code, the call to Invoke is left intact.\n            // Watch https://github.com/dotnet/roslyn/issues/5835\n            return scheduler.Schedule(action, static (_, a) => Invoke(a));\n        }\n\n        /// <summary>\n        /// Schedules an action to be executed.\n        /// </summary>\n        /// <param name=\"scheduler\">Scheduler to execute the action on.</param>\n        /// <param name=\"state\">A state object to be passed to <paramref name=\"action\"/>.</param>\n        /// <param name=\"action\">Action to execute.</param>","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Concurrency/Scheduler.Simple.cs#L9-L45","documentation":"This is the action-null branch of the same Schedule(Action) extension: the scheduler was valid but the Action delegate passed for scheduling is null, so ArgumentNullException with paramName \"action\" is thrown. Rx validates both arguments up front.","triggerScenarios":"Calling scheduler.Schedule(null) or passing a null delegate variable: e.g. scheduler.Schedule(myAction) where myAction is an uninitialized Action field, or a method returning null Action that is forwarded directly into Schedule.","commonSituations":"Optional callbacks wired only under certain conditions that end up null; reflection or configuration-built delegates that failed to resolve; refactors that removed a lambda assignment but left the Schedule call.","solutions":["Pass a non-null lambda or delegate, even a no-op such as () => { }","Check the delegate-producing code path and give it a default value before scheduling","Guard the call: only schedule when the callback is non-null, otherwise run it inline or skip"],"exampleFix":"// before\nAction callback = GetCallback(); // may be null\nscheduler.Schedule(callback); // throws\n\n// after\nAction callback = GetCallback() ?? (() => { });\nscheduler.Schedule(callback);","handlingStrategy":"validation","validationCode":"if (action is null)\n    action = () => { }; // no-op default\nscheduler.Schedule(action);","typeGuard":"bool IsRunnable(Action? a) => a is not null;","tryCatchPattern":"try\n{\n    scheduler.Schedule(callback);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"action\")\n{\n    scheduler.Schedule(() => { });\n}","preventionTips":["Initialize Action fields with a no-op instead of null","Make factory methods that produce callbacks return no-op delegates rather than null","Validate optional callbacks before passing them to Schedule"],"tags":["reactive","null-reference","argument-null","delegate"],"backgroundTag":"null-argument","analyzedSha":"94b5d5ab912789f5abe9a72138a25bbd716fe59c","analyzedAt":"2026-09-15T02:26:24.759Z","contentChangedAt":"2026-09-15T02:26:24.759Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}