dotnet/reactive · error · InvalidOperationException

The asynchronous operation failed with a null error code.

Error message

The asynchronous operation failed with a null error code.

What it means

AsyncInfoToObservableBridge.Done inspects the IAsyncInfo status after the operation finishes. When status is AsyncStatus.Error, it reads info.ErrorCode to propagate the failure; if ErrorCode is also null the implementation is considered rogue and the bridge throws InvalidOperationException instead of propagating a meaningless null exception.

Solutions

  1. Fix the IAsyncInfo implementation so ErrorCode is always set when status becomes Error.
  2. Wrap the observable subscription in try-catch for InvalidOperationException and substitute a generic exception.
  3. Prefer standard WinRT async sources (IAsyncAction/Operation produced by the OS or Task.AsAsyncAction) that always populate ErrorCode.

Example fix

// before (non-conformant impl)
status = AsyncStatus.Error; // ErrorCode left null
// after
status = AsyncStatus.Error;
ErrorCode = new InvalidOperationException("actual failure");
Defensive patterns

Strategy: try-catch

Validate before calling

if (info.Status == AsyncStatus.Error && info.ErrorCode == null)
    throw new InvalidOperationException("Rogue async implementation: Error with null ErrorCode");

Type guard

bool HasErrorCode(IAsyncInfo info) => info.Status != AsyncStatus.Error || info.ErrorCode != null;

Try / catch

try { await obs; }
catch (InvalidOperationException ex) when (ex.Message.Contains("null error code"))
{ /* treat as non-conformant source; substitute generic error */ }

Prevention

When it happens

Trigger: An IAsyncInfo implementation reports AsyncStatus.Error but its ErrorCode property returns null (a non-conformant WinRT async implementation), observed during Done processing.

Common situations: Custom or third-party WinRT async implementations that fail to set ErrorCode when transitioning to the Error state; interop with hand-rolled IAsyncOperation wrappers.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive.WindowsRuntime/AsyncInfoToObservableBridge.cs:49

                progress?.Report(p);
            });

            Done(info, info.Status, true);
        }

        private void Done(IAsyncInfo info, AsyncStatus status, bool initial)
        {
            var error = default(Exception);
            var result = default(TResult);

            //
            // Initial interactions with the IAsyncInfo object. Those could fail, which indicates
            // a rogue implementation. Failure is just propagated out.
            //
            switch (status)
            {
                case AsyncStatus.Error:
                    error = info.ErrorCode ?? throw new InvalidOperationException("The asynchronous operation failed with a null error code.");
                    break;
                case AsyncStatus.Canceled:
                    error = new OperationCanceledException();
                    break;
                case AsyncStatus.Completed:
                    if (_getResult != null)
                    {
                        result = _getResult(info);
                    }

                    break;
                default:
                    if (!initial)
                    {
                        throw new InvalidOperationException("The asynchronous operation completed unexpectedly.");
                    }

                    _onCompleted(info, (iai, s) => Done(iai, s, false));

View on GitHub (pinned to 94b5d5ab91)