Skip to content

Throw meaningful exception when async JSInvokable method is called synchronously from JS#65880

Open
iamcymentho wants to merge 1 commit intodotnet:mainfrom
iamcymentho:iamcymentho/fix-jsinterop-sync-async-error-message
Open

Throw meaningful exception when async JSInvokable method is called synchronously from JS#65880
iamcymentho wants to merge 1 commit intodotnet:mainfrom
iamcymentho:iamcymentho/fix-jsinterop-sync-async-error-message

Conversation

@iamcymentho
Copy link

Summary

Fixes #46811

When a [JSInvokable] method that returns Task or ValueTask is invoked synchronously from JavaScript via invokeMethod(), the raw Task/ValueTask object gets serialized, producing misleading JSON errors like:

  • "SerializeTypeInstanceNotSupported, System.Action"
  • "ConstructorContainsNullParameterNames, System.Threading.Tasks.Task'1"

These errors make debugging difficult as they are unrelated to the actual problem.

Changes

DotNetDispatcher.cs - In the Invoke() method (sync code path), added a check after InvokeSynchronously() returns to detect async return types (Task, ValueTask, ValueTask<T>). When detected, throws an InvalidOperationException with a clear message:

"The method 'MethodName' returns an asynchronous type and cannot be invoked synchronously from JavaScript. Use 'invokeMethodAsync' instead of 'invokeMethod'."

DotNetDispatcherTest.cs - Added 2 tests and 1 test helper:

  • SyncInvokeOfAsyncMethod_Task_ThrowsMeaningfulException
  • SyncInvokeOfAsyncMethod_ValueTask_ThrowsMeaningfulException
  • InvokableAsyncReturningTask() - simple [JSInvokable] test method

Test results

All 148 JSInterop tests pass with 0 failures.

Test plan

  • SyncInvokeOfAsyncMethod_Task - verifies Task-returning methods throw clear error
  • SyncInvokeOfAsyncMethod_ValueTask - verifies ValueTask-returning methods throw clear error
  • Full JSInterop test suite passes (148/148)

@iamcymentho iamcymentho requested a review from a team as a code owner March 20, 2026 11:15
Copilot AI review requested due to automatic review settings March 20, 2026 11:15
@github-actions github-actions bot added the needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically label Mar 20, 2026
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Mar 20, 2026
@martincostello martincostello added area-blazor Includes: Blazor, Razor Components and removed needs-area-label Used by the dotnet-issue-labeler to label those issues which couldn't be triaged automatically labels Mar 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the developer experience for JS interop by detecting when an async [JSInvokable] method is invoked via the synchronous JS path (invokeMethod()), and throwing a clear InvalidOperationException instead of letting Task/ValueTask be serialized into misleading JSON-related errors.

Changes:

  • Add sync-path detection for Task, ValueTask, and ValueTask<T> return values in DotNetDispatcher.Invoke(), throwing a targeted error message.
  • Add new unit tests covering sync invocation of Task-returning and ValueTask-returning [JSInvokable] methods.
  • Add a small test helper [JSInvokable] method that returns Task.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs Adds sync-path check for async return types and throws a clearer exception before serialization.
src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetDispatcherTest.cs Adds tests to validate the new exception behavior for Task and ValueTask sync invocation.

@iamcymentho iamcymentho force-pushed the iamcymentho/fix-jsinterop-sync-async-error-message branch from bfacf3d to f28aff8 Compare March 20, 2026 11:24
…nchronously from JS

When a [JSInvokable] method that returns Task or ValueTask is invoked
synchronously from JavaScript via invokeMethod(), the raw Task/ValueTask
object gets serialized, producing misleading JSON errors like
"SerializeTypeInstanceNotSupported, System.Action". This makes debugging
difficult as the error is unrelated to the actual issue.

Add a check in DotNetDispatcher.Invoke() to detect async return types
(Task, ValueTask, ValueTask<T>) and throw an InvalidOperationException
with a clear message guiding the developer to use invokeMethodAsync().

Fixes dotnet#46811
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-blazor Includes: Blazor, Razor Components community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Calling Asynchronous .NET JS Interop Method Synchronously from JS Produces Misleading Error Message

3 participants