dotnet/aspnetcore · error

The current dispatcher does not support synchronous calls fr

Error message

The current dispatcher does not support synchronous calls from JS to .NET. Use invokeDotNetMethodAsync instead.

What it means

Thrown by DotNet.invokeDotNetMethod when the active call dispatcher has no synchronous invokeDotNetFromJS implementation. This is a capability mismatch: Blazor WebAssembly registers a synchronous dispatcher (the .NET runtime is in-process), but Blazor Server and other remoting-based hosts only expose beginInvokeDotNetFromJS because the call must cross a network boundary asynchronously. The message explicitly redirects you to the async path.

Source

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

          this.completePendingCall(parseInt(asyncCallId, 10), success, resultOrError);
      }

      invokeDotNetStaticMethod<T>(assemblyName: string, methodIdentifier: string, ...args: any[]): T | null {
          return this.invokeDotNetMethod<T>(assemblyName, methodIdentifier, null, args);
      }

      invokeDotNetStaticMethodAsync<T>(assemblyName: string, methodIdentifier: string, ...args: any[]): Promise<T> {
          return this.invokeDotNetMethodAsync<T>(assemblyName, methodIdentifier, null, args);
      }

      invokeDotNetMethod<T>(assemblyName: string | null, methodIdentifier: string, dotNetObjectId: number | null, args: any[] | null): T | null {
          if (this._dotNetCallDispatcher.invokeDotNetFromJS) {
              const argsJson = stringifyArgs(this, args);
              const resultJson = this._dotNetCallDispatcher.invokeDotNetFromJS(assemblyName, methodIdentifier, dotNetObjectId, argsJson);
              return resultJson ? parseJsonWithRevivers(this, resultJson) : null;
          }

          throw new Error("The current dispatcher does not support synchronous calls from JS to .NET. Use invokeDotNetMethodAsync instead.");
      }

      invokeDotNetMethodAsync<T>(assemblyName: string | null, methodIdentifier: string, dotNetObjectId: number | null, args: any[] | null): Promise<T> {
          if (assemblyName && dotNetObjectId) {
              throw new Error(`For instance method calls, assemblyName should be null. Received '${assemblyName}'.`);
          }

          const asyncCallId = this._nextAsyncCallId++;
          const resultPromise = new Promise<T>((resolve, reject) => {
              this._pendingAsyncCalls[asyncCallId] = { resolve, reject };
          });

          try {
              const argsJson = stringifyArgs(this, args);
              this._dotNetCallDispatcher.beginInvokeDotNetFromJS(asyncCallId, assemblyName, methodIdentifier, dotNetObjectId, argsJson);
          } catch (ex) {
              // Synchronous failure
              this.completePendingCall(asyncCallId, false, ex);

View on GitHub (pinned to 294cab2f9b)

Solutions

  1. Switch the JS call to the async variant: DotNet.invokeMethodAsync('MyAssembly','MyMethod') or dotNetRef.invokeMethodAsync('Method').
  2. If you control the call site, make the surrounding function async and await the result.
  3. Avoid DotNetObject.invokeMethod / DotNet.invokeMethod entirely in code that must run on Blazor Server; keep only the async overloads.
  4. If you truly need sync semantics, run that code only on Blazor WebAssembly and gate the host via feature detection.

Example fix

// before
const result = DotNet.invokeMethod('MyAssembly', 'Calculate', input);

// after
const result = await DotNet.invokeMethodAsync('MyAssembly', 'Calculate', input);
Defensive patterns

Strategy: fallback

Validate before calling

function canSyncInvokeDotNet() {
  // dispatcher is internal; approximate by host detection
  return typeof Blazor !== 'undefined' && /WebAssembly/.test(navigator.userAgent) && location.protocol.startsWith('http');
}

Type guard

type DotNetSyncCapable = { invokeMethod(...args:any[]): any };
function supportsSyncDotNet(d: any): d is DotNetSyncCapable {
  return typeof d?.invokeMethod === 'function' && !String(d.invokeMethod).includes('throw');
}

Try / catch

try {
  DotNet.invokeMethod('Asm','M');
} catch (e) {
  if (/Use invokeDotNetMethodAsync/.test(e.message)) {
    return await DotNet.invokeMethodAsync('Asm','M');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling DotNet.invokeMethod / invokeMethodAsync-synchronously on a host that does not set _dotNetCallDispatcher.invokeDotNetFromJS. Concretely: a JS module calls DotNet.invokeMethod('MyAssembly','MyMethod') under Blazor Server, or a JS component calls dotNetRef.invokeMethod(...) (DotNetObject.invokeMethod at Microsoft.JSInterop.ts:710) on Blazor Server.

Common situations: Running the same JS interop code against Blazor Server that worked on Blazor WebAssembly; library code that assumed an in-process .NET runtime; misreading the docs and using the sync overload everywhere.

Related errors


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