dotnet/reactive · error · ArgumentNullException
stateMachine
Error message
stateMachine
What it means
AsyncTaskMethodBuilder-style Start<TStateMachine> in the custom TaskObservableMethodBuilder throws ArgumentNullException when the state machine box is null. The compiler-generated async state machine is passed by ref to Start, which calls MoveNext to begin execution; a null machine cannot run. This builder is used by async methods returning IObservable-based tasks, and null here almost always means the async method builder infrastructure was invoked incorrectly.
Solutions
- Do not call Start manually — let the C# compiler construct and start the state machine for async methods using this builder.
- If you must call it, construct the TStateMachine struct (never pass null/default-of-reference) before Start.
- Check that IL-rewriting tooling (profiler, weaver, mocking library) supports this async method builder and is up to date.
- Rebuild/reinstall System.Reactive so compiler-generated builder bindings match the library version.
Example fix
// before
TaskObservableMethodBuilder<int> b = default;
MyStateMachine machine = null; // invalid
b.Start(ref machine);
// after
var b = TaskObservableMethodBuilder<int>.Create();
var machine = new MyStateMachine { Builder = b };
b.Start(ref machine); // compiler does this automatically for async methods Defensive patterns
Strategy: try-catch
Validate before calling
if (stateMachine == null) throw new ArgumentNullException(nameof(stateMachine)); // guard before calling builder.Start
Type guard
bool CanStart<TStateMachine>(TStateMachine m) where TStateMachine : class, IAsyncStateMachine => m != null;
Try / catch
try { builder.Start(ref stateMachine); }
catch (ArgumentNullException ex) when (ex.ParamName == "stateMachine") { /* state machine was not constructed; inspect async tooling/rewriters */ throw; } Prevention
- Let the compiler drive async method builders; avoid manual Start calls
- Keep IL-weaving/profiler tooling compatible with System.Reactive's builders
- Rebuild after upgrading System.Reactive so generated code matches
When it happens
Trigger: Calling builder.Start<TStateMachine>(ref machine) manually with an uninitialized (null) state machine, or custom/rewritten async tooling (e.g. post-processing IL rewriters, custom awaiter libraries) that fails to construct the state machine struct before calling Start.
Common situations: Custom async-method-builder experiments targeting Rx observables; IL-weaving or AOP frameworks (profilers, mocking tools) that rewrite async state machines; debugging stepping into builder internals after a broken build.
Related errors
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- null (Parameter 'scheduler')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/58c7ac036e6ec392.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Runtime/CompilerServices/TaskObservableMethodBuilder.cs:54
#pragma warning disable CA1000 // (Do not declare static members on generic types.) Async method builders are required to define a static Create method, and are require to be generic when the async type produces a result.
public static TaskObservableMethodBuilder<T> Create() => default;
#pragma warning restore CA1000 // Do not declare static members on generic types
/// <summary>
/// Begins running the builder with the associated state machine.
/// </summary>
/// <typeparam name="TStateMachine">The type of the state machine.</typeparam>
/// <param name="stateMachine">The state machine instance, passed by reference.</param>
/// <exception cref="ArgumentNullException"><paramref name="stateMachine"/> is <c>null</c>.</exception>
#pragma warning disable CA1045 // (Avoid ref.) Required because this is an async method builder
#pragma warning disable IDE0251 // (Make readonly.) Not part of the standard method builder pattern.
public void Start<TStateMachine>(ref TStateMachine stateMachine)
#pragma warning restore CA1045, IDE0251
where TStateMachine : IAsyncStateMachine
{
if (stateMachine == null)
{
throw new ArgumentNullException(nameof(stateMachine));
}
stateMachine.MoveNext();
}
/// <summary>
/// Associates the builder with the specified state machine.
/// </summary>
/// <param name="stateMachine">The state machine instance to associate with the builder.</param>
/// <exception cref="ArgumentNullException"><paramref name="stateMachine"/> is <c>null</c>.</exception>
/// <exception cref="InvalidOperationException">The state machine was previously set.</exception>
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
if (_stateMachine != null)
{
throw new InvalidOperationException();
}
View on GitHub (pinned to 94b5d5ab91)