dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'end')

Error message

Value cannot be null. (Parameter 'end')

What it means

FromAsyncPattern<T1..T5> adapts a Begin/End APM pair into a function returning an IAsyncObservable, and it throws ArgumentNullException with parameter name 'end' when the end callback (Func<IAsyncResult, Unit>) is null. A Begin/End pair is meaningless without the End delegate that extracts the result, so it is validated eagerly when the pattern is constructed. The exception is thrown at FromAsyncPattern call time, not when the returned function is invoked.

Solutions

  1. Pass the matching End method: FromAsyncPattern(begin, r => (Unit)EndXxx(r)) or via method group EndXxx.
  2. Verify reflection lookups (Type.GetMethod for the End method) are not returning null.
  3. Null-check both delegates before constructing the pattern and surface a domain-specific error.

Example fix

// before
var f = AsyncObservable.FromAsyncPattern<string, int, int, int, int>(req.BeginGetResponse, null);
// after
var f = AsyncObservable.FromAsyncPattern<string, int, int, int, int>(req.BeginGetResponse, r => { req.EndGetResponse(r); return Unit.Default; });
Defensive patterns

Strategy: validation

Validate before calling

if (begin is null || end is null) throw new InvalidOperationException("FromAsyncPattern requires a complete begin/end pair");

Type guard

bool IsCompletePair(Delegate begin, Delegate end) => begin is not null && end is not null;

Try / catch

try { var f = AsyncObservable.FromAsyncPattern<T1,T2,T3,T4,T5>(begin, end); }
catch (ArgumentNullException ex) when (ex.ParamName == "end") { /* log and rebuild with correct End method */ }

Prevention

When it happens

Trigger: Calling FromAsyncPattern(begin, end) with a null end delegate, e.g. the five-generic-argument overload where only begin was supplied or the end lambda was conditionally omitted.

Common situations: Migrating legacy APM (BeginXxx/EndXxx) APIs where the End method lookup via reflection returned null; wrapping WebRequest-style APIs with partially defined pairs.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromAsyncPattern.Generated.cs:498

                try
                {
                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4);
                }
                catch (Exception ex)
                {
                    return Throw<Unit>(ex);
                }

                return subject.AsAsyncObservable();
            };
        }

        public static Func<T1, T2, T3, T4, T5, IAsyncObservable<Unit>> FromAsyncPattern<T1, T2, T3, T4, T5>(Func<T1, T2, T3, T4, T5, AsyncCallback, object, IAsyncResult> begin, Func<IAsyncResult, Unit> end)
        {
            if (begin == null)
                throw new ArgumentNullException(nameof(begin));
            if (end == null)
                throw new ArgumentNullException(nameof(end));

            return (arg1, arg2, arg3, arg4, arg5) =>
            {
                var subject = new SequentialAsyncAsyncSubject<Unit>();

                try
                {
                    AsyncObserver.FromAsyncPattern(subject, begin, end, arg1, arg2, arg3, arg4, arg5);
                }
                catch (Exception ex)
                {
                    return Throw<Unit>(ex);
                }

                return subject.AsAsyncObservable();
            };
        }

View on GitHub (pinned to 94b5d5ab91)