{"record":{"id":"fe27dee496eea61d","repo":"dotnet/reactive","slug":"value-cannot-be-null-parameter-action-schedulerwrapper","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":"Rx.NET/Source/src/System.Reactive/Concurrency/SchedulerWrapper.cs","lineNumber":36,"sourceCode":"\n        protected SchedulerWrapper(IScheduler scheduler)\n        {\n            _scheduler = scheduler;\n        }\n\n        protected SchedulerWrapper(IScheduler scheduler, ConditionalWeakTable<IScheduler, IScheduler> cache)\n        {\n            _scheduler = scheduler;\n            _cache = cache;\n        }\n\n        public DateTimeOffset Now => _scheduler.Now;\n\n        public IDisposable Schedule<TState>(TState state, Func<IScheduler, TState, IDisposable> action)\n        {\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action));\n            }\n\n            return _scheduler.Schedule(state, Wrap(action));\n        }\n\n        public IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action)\n        {\n            if (action == null)\n            {\n                throw new ArgumentNullException(nameof(action));\n            }\n\n            return _scheduler.Schedule(state, dueTime, Wrap(action));\n        }\n\n        public IDisposable Schedule<TState>(TState state, DateTimeOffset dueTime, Func<IScheduler, TState, IDisposable> action)\n        {\n            if (action == null)","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/dotnet/reactive/blob/94b5d5ab912789f5abe9a72138a25bbd716fe59c/Rx.NET/Source/src/System.Reactive/Concurrency/SchedulerWrapper.cs#L18-L54","documentation":"This is an ArgumentNullException thrown by SchedulerWrapper.Schedule<TState>(TState, Func<IScheduler,TState,IDisposable>) when the scheduling action delegate is null. SchedulerWrapper decorates an IScheduler and forwards calls to the inner scheduler after wrapping the action, so it validates the delegate up front to avoid a null surfacing later inside the wrapped schedule pipeline.","triggerScenarios":"Calling scheduler.Schedule(state, action) (immediate, no due time) on a SchedulerWrapper with a null Func<IScheduler,TState,IDisposable>, typically because a lambda variable was null, a conditional factory returned null, or a method group bound to a null instance.","commonSituations":"Passing the result of a function that conditionally returns a delegate; storing callbacks in a nullable field or property that has not been initialized; refactoring code where the action lambda was accidentally removed or replaced by a null-returning expression.","solutions":["Ensure the Func<IScheduler,TState,IDisposable> passed as the last argument to Schedule is a non-null delegate (e.g. (scheduler, state) => ...).","If the delegate comes from a variable or factory, check it for null before calling Schedule and provide a default no-op action returning Disposable.Empty.","Pass null state instead of a null action when the intent was to schedule without a value; only the action parameter may not be null.","Review code that builds the delegate dynamically (reflection, conditional expressions) and add a null check at construction time."],"exampleFix":"// before\nFunc<IScheduler, int, IDisposable> action = GetAction();\nschedulerWrapper.Schedule(42, action); // action may be null\n// after\nFunc<IScheduler, int, IDisposable> action = GetAction() ?? ((s, st) => Disposable.Empty);\nschedulerWrapper.Schedule(42, action);","handlingStrategy":"validation","validationCode":"if (action == null) throw new InvalidOperationException(\"Schedule requires a non-null action delegate\");\nschedulerWrapper.Schedule(state, action);","typeGuard":"bool IsValidAction<TState>(Func<IScheduler, TState, IDisposable> action) => action != null;","tryCatchPattern":"try\n{\n    schedulerWrapper.Schedule(state, action);\n}\ncatch (ArgumentNullException ex) when (ex.ParamName == \"action\")\n{\n    schedulerWrapper.Schedule(state, (s, st) => Disposable.Empty);\n}","preventionTips":["Never build schedule actions via expressions that can return null; default to a no-op returning Disposable.Empty.","Null-check delegate arguments where they are created, not at the scheduling call site.","Avoid storing callbacks in uninitialized fields; initialize them with a default no-op lambda.","When scheduling optional work, branch around the Schedule call instead of passing null."],"tags":["csharp","dotnet","null-argument","scheduler","rx"],"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"}