dotnet/reactive · error · InvalidOperationException
The observer has already terminated.
Error message
The observer has already terminated.
What it means
TryEnter is a serialization guard on the observer's status: it uses Interlocked.CompareExchange to ensure only one notification is processed at a time. This message fires when the status is Done, i.e. OnErrorAsync or OnCompletedAsync was already called and the observer is terminated — any further OnNextAsync/OnErrorAsync/OnCompletedAsync is illegal. Fix: stop issuing notifications after termination, or create a fresh observer.
Solutions
- Stop emitting from the source once OnCompleted/OnError has been signaled (e.g. gate emission with the subscription disposable).
- Track termination state in the producer before calling OnNextAsync.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at AsyncRx.NET/System.Reactive.Async/AsyncObserverBase.cs:78 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/0095d10d20c0698c.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/AsyncObserverBase.cs:78
}
finally
{
Interlocked.Exchange(ref _status, Idle);
}
}
protected abstract ValueTask OnNextAsyncCore(T value);
private void TryEnter()
{
var old = Interlocked.CompareExchange(ref _status, Busy, Idle);
switch (old)
{
case Busy:
throw new InvalidOperationException("The observer is currently processing a notification.");
case Done:
throw new InvalidOperationException("The observer has already terminated.");
}
}
}
}
View on GitHub (pinned to 94b5d5ab91)