dotnet/maui · info · ArgumentException

This is an async test exception thrown from C# code!

Error message

This is an async test exception thrown from C# code!

What it means

This is a deliberate demo exception thrown by the HybridWebView sample app. The ThrowExceptionAsync() method (an inner-class RPC target invokable from JavaScript) awaits a short delay and then throws ArgumentException to demonstrate how async exceptions cross the JS/C# boundary. It is not a library fault; it is sample code exercising HybridWebView's error-propagation contract.

Source

Thrown at src/Controls/samples/Controls.Sample/Pages/Controls/HybridWebViewPage.xaml.cs:215

				{
					Message = "Hello from C#! " + s,
					Value = i,
				};
			}

			// Demo method that throws an exception to showcase error handling
			public void ThrowException()
			{
				Debug.WriteLine("ThrowException called - about to throw");
				throw new InvalidOperationException("This is a test exception thrown from C# code!");
			}

			// Demo async method that throws an exception
			public async Task<string> ThrowExceptionAsync()
			{
				Debug.WriteLine("ThrowExceptionAsync called - about to throw");
				await Task.Delay(100);
				throw new ArgumentException("This is an async test exception thrown from C# code!");
			}
		}

		public class SyncReturn
		{
			public string? Message { get; set; }
			public int Value { get; set; }
		}
	}
}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. If you copied the sample proxy class, replace throw new ArgumentException(...) with your real async logic.
  2. If intentionally testing, keep the call inside the JS try/catch the sample already provides around InvokeDotNet.
  3. Confirm you are not invoking the demo ThrowExceptionAsync method from production code paths.

Example fix

// before
public async Task<string> ThrowExceptionAsync()
{
    await Task.Delay(100);
    throw new ArgumentException("This is an async test exception thrown from C# code!");
}

// after
public async Task<string> GetDataAsync()
{
    await Task.Delay(100);
    return "real payload";
}
Defensive patterns

Strategy: try-catch

Try / catch

// JS side (the sample already does this)
try {
  const result = await window.HybridWebView.InvokeDotNet('ThrowExceptionAsync');
} catch (ex) {
  console.error(ex.message, ex.dotNetErrorType);
}

// C# side, if calling directly
try { await proxy.ThrowExceptionAsync(); }
catch (ArgumentException) { /* expected in tests */ }

Prevention

When it happens

Trigger: Invoking ThrowExceptionAsync from JavaScript via window.HybridWebView.InvokeDotNet('ThrowExceptionAsync') (e.g. the sample's 'Test C# Async Exception Handling' button), or calling it directly from C#.

Common situations: Running the Controls.Sample HybridWebView page and clicking the async-exception test button; copy-pasting the sample's RPC proxy class into a real app and forgetting to remove the throw; automated UI tests that walk every sample button.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/2d34f7054baef93c. Report an issue: GitHub.