Fix: async void crashes in ASP.NET Core

Published: Jun 01, 2026 · By Kumar Kunal

The Error

Random 500 errors. Logs show:

System.InvalidOperationException: An asynchronous module or handler completed while an asynchronous operation was still pending.

Quick Fix - 1 Minute

Change async void to async Task.

Wrong:

[HttpGet]
public async void GetData() { await _service.DoWorkAsync(); }

Right:

[HttpGet]
public async Task<IActionResult> GetData() 
{ 
    await _service.DoWorkAsync(); 
    return Ok();
}

Why This Happens

ASP.NET can't await void. It thinks the request finished and sends response. Your await runs after, so exceptions crash the app. Never use async void except event handlers.

Real-World Scenario: Fire-and-Forget in Controller

#1 cause of prod crashes. Dev tries to "not block" the request:

// WRONG: async void - Request ends before work finishes
[HttpPost("/orders")]
public async void CreateOrder(OrderDto dto)
{
    await _db.Orders.AddAsync(dto); // Dev Fix: This throws after response sent
    await _db.SaveChangesAsync();
    _emailService.SendAsync(dto.Email); // Exception here crashes entire app
}

// RIGHT: Return Task and use background queue for long work [HttpPost("/orders")] public async Task<IActionResult> CreateOrder(OrderDto dto) { await _db.Orders.AddAsync(dto); await _db.SaveChangesAsync();

// Dev Fix: Queue long work, don't await it
_backgroundQueue.QueueBackgroundWorkItem(async token =>
{
    await _emailService.SendAsync(dto.Email, token);
});

return Accepted(); // 202 - "I'll process this"

}

// For .NET 8: Use IHostApplicationLifetime + Channel<T> public interface IBackgroundTaskQueue { void QueueBackgroundWorkItem(Func<CancellationToken, Task> workItem); Task<Func<CancellationToken, Task>> DequeueAsync(CancellationToken token); }

Why async void kills apps: ASP.NET Core has a SynchronizationContext. When your controller returns, it disposes the request. Any async void continuation runs on disposed context = crash. async Task lets ASP.NET track the operation.

Related Fixes You Should Know

async void bugs create these downstream issues:

FAQ

Q: When is async void actually OK?

Only for event handlers: button_Click, OnStartup. Never in ASP.NET Core, libraries, or anything that returns to a framework. Event handlers are top-level, so no one awaits them anyway.

Q: How do I do fire-and-forget without async void?

Use IHostedService + Channel<T> or Hangfire. Return 202 Accepted to client immediately. Queue the work. Never async void or Task.Run() without tracking.

Common Scenarios

  • Controller actions: Must return Task or Task<IActionResult>
  • Service methods: If called with await, must return Task
  • Fire-and-forget: Don't. Use IHostedService or background queue

Best Practice

Install Microsoft.VisualStudio.Threading.Analyzers. It marks async void as compile error. Add Async suffix: SaveAsync().

Related Dev Fixes

Found this helpful?

Master C# with our complete course. Real apps, real skills, job-ready in 2 hours.

Share this fix: Twitter LinkedIn

Comments on Fix: async void crashes in ASP.NET Core (0)

No comments yet. Be the first to share your thoughts!