dotnet/aspnetcore · error

There is no pending async call with ID ${asyncCallId}.

Error message

There is no pending async call with ID ${asyncCallId}.

What it means

Thrown by completePendingCall when _pendingAsyncCalls has no entry for the given asyncCallId. Each async JS<->.NET call registers a deferred resolver/rejector keyed by an incrementing id; completion removes it. The id is unknown if it was already completed (double completion), cleared on disconnect, or generated by a stale/out-of-process message.

Source

Thrown at src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts:550

          // it's not something the developer gets to control, and it would be an error if it doesn't.
          let result: Promise<ReadableStream>;
          if (this._pendingDotNetToJSStreams.has(streamId)) {
              // We've already started receiving the stream, so no longer need to track it as pending
              result = this._pendingDotNetToJSStreams.get(streamId)!.streamPromise!;
              this._pendingDotNetToJSStreams.delete(streamId);
          } else {
              // We haven't started receiving it yet, so add an entry to track it as pending
              const pendingStream = new PendingStream();
              this._pendingDotNetToJSStreams.set(streamId, pendingStream);
              result = pendingStream.streamPromise;
          }

          return result;
      }

      private completePendingCall(asyncCallId: number, success: boolean, resultOrError: any) {
          if (!this._pendingAsyncCalls.hasOwnProperty(asyncCallId)) {
              throw new Error(`There is no pending async call with ID ${asyncCallId}.`);
          }

          const asyncCall = this._pendingAsyncCalls[asyncCallId];
          delete this._pendingAsyncCalls[asyncCallId];
          if (success) {
              asyncCall.resolve(resultOrError);
          } else {
              asyncCall.reject(resultOrError);
          }
      }
  }

  function formatError(error: Error | string): string {
      if (error instanceof Error) {
          return `${error.message}\n${error.stack}`;
      }

      return error ? error.toString() : "null";

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Confirm you are on the latest Blazor runtime version; double-completion is usually a framework bug fixed in patch releases.
  2. Ensure the SignalR connection is not reconnecting mid-call; handle OnConnectionDown and re-issue the call instead of relying on stale callbacks.
  3. If calling framework internals, verify each asyncCallId is completed exactly once.
  4. Guard app-level code with try/catch around the async call so a spurious completion rejection is observable.

Example fix

// before
// relying on a single fire-and-forget that may be completed twice
await dotNetRef.invokeMethodAsync('Op');

// after
try {
  await dotNetRef.invokeMethodAsync('Op');
} catch (e) {
  // a duplicate/stale completion surfaces here
  console.warn('dotnet call failed/stale:', e.message);
}
Defensive patterns

Strategy: try-catch

Validate before calling

null

Type guard

null

Try / catch

try {
  await dotNetRef.invokeMethodAsync('Op');
} catch (e) {
  if (/no pending async call with ID/i.test(e.message)) {
    // stale/duplicate completion; re-issue once on a fresh ref
    return await dotNetRef.invokeMethodAsync('Op');
  }
  throw e;
}

Prevention

When it happens

Trigger: The .NET side calling back to complete a call twice; a reconnect/hot-reload where the JS dispatcher's _nextAsyncCallId counter reset but a queued completion arrives; manually calling DotNet plumbing such as __blazor__ completeAsyncCall more than once. In normal framework usage this indicates a framework-level or transport-level bug rather than app code.

Common situations: Blazor Server reconnect scenarios, dev hot reload, aggressive disposal while async calls are in flight, or a misbehaving custom transport that replays completion frames.

Related errors


AI-assisted analysis of dotnet/aspnetcore@294cab2f9b (2026-08-06). Data as JSON: /api/errors/605ba3e6ce50e61a. Report an issue: GitHub.