dotnet/aspnetcore · error · Error
The current dispatcher does not support synchronous calls…
Error message
The current dispatcher does not support synchronous calls from JS to .NET. Use invokeDotNetMethodAsync instead.
What it means
Thrown by CallDispatcher.invokeDotNetMethod() (the synchronous path) when the underlying DotNetCallDispatcher does not implement invokeDotNetFromJS. Synchronous JS-to-.NET calls are only supported on runtimes that opt in (e.g., Blazor WebAssembly); Blazor Server and other remote runtimes only support the async path.
Solutions
- Switch to the async variant: DotNet.invokeMethodAsync or DotNetObject.invokeMethodAsync.
- If you control the host, implement invokeDotNetFromJS on your DotNetCallDispatcher to enable sync calls.
- Audit for any .invokeMethod( synchronous calls and convert them.
Example fix
// before
const result = DotNet.invokeMethod('MyLib', 'Compute', input); // sync
// after
const result = await DotNet.invokeMethodAsync('MyLib', 'Compute', input); Defensive patterns
Strategy: validation
Validate before calling
// Always prefer the async API; it works on all hosts.
const result = await DotNet.invokeMethodAsync('MyLib', 'Compute', input); Type guard
function supportsSyncInvoke(dispatcher) { return typeof dispatcher.getDotNetCallDispatcher().invokeDotNetFromJS === 'function'; } Try / catch
try { return DotNet.invokeMethod('MyLib', 'Method'); } catch (e) { if (/does not support synchronous calls/.test(e.message)) { return await DotNet.invokeMethodAsync('MyLib', 'Method'); } throw e; } Prevention
- Default to invokeMethodAsync everywhere; reserve sync calls for WebAssembly-only code.
- Document the host requirement for any synchronous interop call.
- Search the codebase for .invokeMethod( and convert to async during Server ports.
When it happens
Trigger: Calling DotNet.invokeMethod or DotNetObject.invokeMethod (synchronous) under Blazor Server or any host whose dispatcher lacks invokeDotNetFromJS. The check `if (this._dotNetCallDispatcher.invokeDotNetFromJS)` is false, so it throws.
Common situations: Code written and tested under Blazor WebAssembly (sync works) then deployed on Blazor Server (sync unsupported); using a third-party host that only wires beginInvokeDotNetFromJS; calling the deprecated DotNet.invokeMethod in a Server project.
Related errors
- For instance method calls, assemblyName should be null…
- No call dispatcher has been set.
- There are multiple .NET runtimes present, so a default…
- There is no pending async call with ID
- Byte array index ' ' does not exist.
AI-assisted analysis of dotnet/aspnetcore@3600ca084e (2026-08-11).
Data as JSON: /api/errors/95b5dd19bb3584c7.
Report an issue: GitHub.
Appendix: 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 3600ca084e)