dotnet/reactive · error · ArgumentNullException

progressSelector (Parameter 'progressSelector')

Error message

progressSelector (Parameter 'progressSelector')

What it means

This ToAsyncActionWithProgress overload throws ArgumentNullException named 'progressSelector' when the supplied progressSelector function is null. The selector defines how source elements map to progress values reported through the WinRT progress handler.

Solutions

  1. Provide a valid progressSelector, e.g. o => o.Select((_, i) => i) for count-based progress
  2. Guard the selector argument before the call if it is optional and fall back to a default selector
  3. Fix the code path that yields a null Func

Example fix

// before
source.ToAsyncActionWithProgress(progressSelector); // progressSelector is null
// after
source.ToAsyncActionWithProgress(progressSelector ?? (o => o.Select((_, i) => (int)i)));
Defensive patterns

Strategy: validation

Validate before calling

if (progressSelector == null) throw new ArgumentNullException(nameof(progressSelector));

Type guard

static bool IsValidSelector<TSource,TProgress>(Func<IObservable<TSource>, IObservable<TProgress>>? selector) => selector is not null;

Try / catch

try { op = source.ToAsyncActionWithProgress(selector); } catch (ArgumentNullException ex) when (ex.ParamName == "progressSelector") { /* supply default selector */ }

Prevention

When it happens

Trigger: Calling source.ToAsyncActionWithProgress(null) or passing a nullable Func variable that was never assigned.

Common situations: Building the selector dynamically (e.g. from config or reflection) and the construction silently produced null; or forwarding an optional parameter straight through.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/c567be994be0af38. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Platforms/WinRT/Linq/AsyncInfoObservable.cs:83

        /// Creates a Windows Runtime asynchronous action that represents the completion of the observable sequence, using a selector function to map the source sequence on a progress reporting sequence.
        /// Upon cancellation of the asynchronous action, the subscription to the source sequence will be disposed.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TProgress">The type of the elements in the progress sequence.</typeparam>
        /// <param name="source">Source sequence to expose as an asynchronous action and to compute a progress sequence that gets reported through the asynchronous action.</param>
        /// <param name="progressSelector">Selector function to map the source sequence on a progress reporting sequence.</param>
        /// <returns>Windows Runtime asynchronous action object representing the completion of the result sequence, reporting progress computed through the progress sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="progressSelector"/> is null.</exception>
        public static IAsyncActionWithProgress<TProgress> ToAsyncActionWithProgress<TSource, TProgress>(this IObservable<TSource> source, Func<IObservable<TSource>, IObservable<TProgress>> progressSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (progressSelector == null)
            {
                throw new ArgumentNullException(nameof(progressSelector));
            }

            return AsyncInfo.Run<TProgress>((ct, progress) =>
            {
                return Observable.Create<TSource?>(observer =>
                {
                    var obs = Observer.Synchronize(observer);

                    var data = source.Publish();

                    var progressSubscription = progressSelector(data).Subscribe(progress.Report, obs.OnError);
                    var dataSubscription = data.DefaultIfEmpty().Subscribe(obs);
                    var connection = data.Connect();

                    return StableCompositeDisposable.CreateTrusted(progressSubscription, dataSubscription, connection);
                }).ToTask(ct);
            });
        }

View on GitHub (pinned to 94b5d5ab91)