Quick answer: WebGPU games fail in ways ordinary error handling misses: the device can be lost asynchronously, adapter selection can return nothing, and validation errors surface through the uncapturederror event rather than a throw. Listen for device.lost, handle a missing adapter gracefully, capture validation errors, and record the adapter, browser, and driver, since WebGPU behavior varies widely across an immature implementation landscape. Group failures by signature to find which configurations break.

WebGPU is the modern successor to WebGL, giving web games real access to the GPU with compute shaders and a lower level API. It is also new, unevenly implemented, and asynchronous in ways that break the assumptions of ordinary error handling. A WebGPU game does not just throw exceptions you can catch; it can lose its device mid frame, fail to get an adapter at all, and surface validation errors through an event rather than a stack. Capturing these failures takes API specific handling. This post covers device lost, adapter and device acquisition, validation errors, the browser variance that defines WebGPU today, and how to report all of it.

Why WebGPU failures are different

Most crash reporting assumes failures arrive as thrown exceptions, but WebGPU's most important failures do not. The GPU device can be lost asynchronously at any time, because the driver reset, the page lost focus on some platforms, or the GPU ran out of memory, and this surfaces as a promise resolving on device.lost, not as a throw in your render code. Adapter acquisition can simply return nothing on a machine that cannot provide a suitable GPU. And validation errors, your misuse of the API, are reported through an error scope or an event rather than by throwing where you made the mistake.

This means a try and catch around your render loop, which would catch a WebGL exception, sees almost none of WebGPU's real failures. You have to subscribe to the specific signals the API exposes: the device lost promise, the return values of the acquisition calls, and the uncapturederror event or pushErrorScope mechanism for validation. Treating WebGPU like a synchronous throwing API is the most common mistake, and it leaves a game blind to exactly the failures that an immature graphics stack produces most often. The capture has to be built around the API's own asynchronous error model.

Device lost and acquisition

When you request a GPU device it exposes a lost property that is a promise; when the device is lost, that promise resolves with a reason and a message. You should always attach a handler to it that captures a report with the reason, whether it was destroyed intentionally or lost due to an error, and then attempt to reacquire a device and rebuild your resources if you want the game to recover. A lost device that you do not handle means every subsequent GPU call fails silently and the game appears to freeze with no error you ever saw.

Acquisition itself can fail before you ever get a device. requestAdapter can resolve to null on a machine with no compatible GPU or where the browser declines to provide one, and requestDevice can reject if the adapter cannot satisfy your requested features or limits. Robust code checks for a null adapter explicitly and reports it with the browser and machine context, rather than dereferencing null and throwing a confusing downstream error. Capturing the failure at the acquisition step, with the requested features and limits in the report, tells you exactly why a given machine could not run your game.

Validation and uncaptured errors

WebGPU validates your API usage, and when you do something invalid, a wrong texture format, a buffer too small, a pipeline mismatch, it does not throw at the call site. Instead the error is delivered to the current error scope if you pushed one, or to the device's uncapturederror event if you did not. For development you wrap suspect operations in pushErrorScope and popErrorScope to catch validation and out of memory errors precisely where they occur. For production you add an uncapturederror listener as a catch all so any validation error that slips through is still reported.

These validation errors are gold for debugging because they describe API misuse in detail, but they are easy to miss precisely because they do not interrupt control flow. A game can run with a validation error firing every frame, producing wrong output or a slow leak, while the developer sees nothing. Capturing the uncapturederror event into your crash reporting, with the message and your current context, surfaces these silent problems. Tagging whether a report came from a pushed scope or the global uncaptured handler tells you whether you caught it deliberately or it escaped, which guides where to tighten your error scopes.

Browser and adapter variance

WebGPU's defining characteristic right now is variance. The API is new, implementations differ across browsers and versions, and the same code can succeed on one browser and one GPU while failing on another due to a different adapter, a driver bug, or an unsupported limit. This makes context not just helpful but essential: every report should carry the adapter info the API exposes, the adapter description and vendor where available, the browser and version, the OS, and the requested versus supported features and limits. These are the exact axes along which WebGPU failures cluster.

Because the landscape is shifting as browsers mature, a crash that is universal today may be a fixed driver bug next month, and one that hits a single adapter may point at a genuine incompatibility you must work around. You cannot tell these apart without the adapter and browser breakdown. Capturing it turns a confusing spread of failures into a clear map of which configurations your game does and does not run on, which for a cutting edge API is often the most important thing to know, both for fixing bugs and for deciding which hardware to officially support.

Setting it up with Bugnet

Bugnet receives WebGPU failures from all these channels into one dashboard with the GPU and browser context attached, so a device lost event, a null adapter, and a validation error each arrive as a contextual report rather than a vanished frame. From your device.lost handler, your acquisition checks, and your uncapturederror listener you forward the reason and message with custom fields for the adapter description, browser, and requested features, and the in game report button lets a player whose screen went black describe what they saw and send the state, which matters because a lost device often shows the player nothing.

The variance that makes WebGPU hard is exactly what occurrence grouping tames: the same failure across many adapters and browsers folds into one issue with a count and a breakdown by your adapter and browser fields, so you see which configurations break and how often. Filtering by adapter vendor or browser version tells you whether a crash is a code bug present everywhere or an incompatibility on specific hardware, which is the central question for a WebGPU game. The occurrence counts then rank the configurations by player impact, so you spend your effort where the most players are losing their device.

Testing on real hardware

WebGPU cannot be validated on one machine. Behavior depends on the adapter and driver, so you test crash reporting across several browsers and at least a couple of GPU vendors: trigger a device lost by exhausting memory or forcing a context, request a device with limits the adapter cannot meet to exercise the rejection path, and deliberately issue an invalid operation to confirm the uncapturederror listener fires. Each should produce a contextual report. Verify on a machine where requestAdapter returns null too, so the no GPU path is covered, not just the happy path.

As WebGPU and its implementations stabilize, the crash data you collect becomes a living record of where the API stands for your game. You learn which adapters lose devices, which browsers reject your limits, and which validation mistakes slipped into production, all grouped by configuration. For a team adopting a young graphics API, that visibility is what makes the bet safe: you ship into the variance with your eyes open, fix the failures that affect the most players, and adjust your supported hardware as the picture clarifies, instead of guessing at a moving target.

WebGPU fails asynchronously: lost devices, null adapters, uncaptured validation errors. Subscribe to each signal and record the adapter, since variance is the whole story.