Quick answer: Asynchronous multiplayer bugs live in turn state and synchronization: a turn that did not register, two players who see different board states, or a notification that never arrived. Because players act at different times across devices and servers, the game state can diverge in ways neither player can see. Capture the local and server turn state, the version or sequence each side holds, and the notification status when a report fires, and a vague desync becomes a reproducible conflict.
Asynchronous multiplayer, the play-by-mail model behind many strategy and puzzle games, lets players take turns hours or days apart without being online together. The server holds the authoritative game state and each player syncs to it when they open the app. That convenience hides real complexity: turns submitted from stale state, conflicts when two devices diverge, and notifications that decide whether a player even knows it is their move. When a player reports that their move vanished, that the board looks wrong, or that they never got told it was their turn, the relevant state is split across their device and the server. This post covers the turn, sync, and notification state worth capturing.
Why asynchronous play diverges
In synchronous multiplayer everyone shares one live session, but in asynchronous play each participant holds their own copy of the game state and reconciles with the server whenever they connect. Between syncs, a player's device can hold a stale view: the opponent may have moved, but this player has not pulled the update. When they then act on the old state and submit, the server has to decide whether the move is still valid against the current authoritative state. Most asynchronous bugs are this reconciliation going wrong, and the player only sees the confusing result, not the version mismatch behind it.
These bugs are hard to reproduce because they depend on the interleaving of actions across time and devices, which you cannot recreate by playing both sides quickly on one machine. A conflict only appears when one player submits from a state the server has already advanced past, and that requires a specific sequence of who synced when. Without capturing what version each side held at the moment of the problem, you are left comparing two players' descriptions of a board, which they each saw at different times. The version and sequence state is the only objective record of the divergence.
Capturing turn state
The foundation is the turn state on both the device and the server. Capture whose turn the client believed it was, the turn or move number the client held, the game state version it was synced to, and the corresponding values the server held. A player who reports that their move did not register often submitted while the client thought it was their turn but the server had already recorded a move, and the mismatch between the client's turn number and the server's is the whole diagnosis. Seeing both numbers side by side turns a lost move into an obvious stale submission.
Capture the submitted action itself and its fate. Record the move the player tried to make, the timestamp, whether the server accepted, rejected, or queued it, and the reason for any rejection. A move rejected because it was illegal against the current state is a very different bug from one lost in transit, and only the server's verdict distinguishes them. When the captured action shows the server rejected a move that was legal on the stale client state, you have found a reconciliation bug where the client allowed an action the authoritative state no longer permitted, which is exactly the kind of defect descriptions never reveal.
Synchronization and conflict resolution
The sync layer is where divergence is detected and resolved, so capture its state. Record the game state version or hash the client held, the version the server held, and the last successful sync time. When two players report seeing different boards, comparing their held versions against the server's immediately shows who was stale and by how much. A client several versions behind that never pulled the latest state explains a wrong board with no further investigation, and the last-sync time tells you whether the device simply failed to reconcile or reconciled to a wrong result.
Conflict resolution policy matters when versions diverge, so capture how a conflict was resolved. If your system uses last-write-wins, server-authority, or a merge, record which path was taken and what was discarded. The most painful asynchronous bugs are silent losses: a player's move was overwritten by a conflict resolution they never saw. Capturing the resolution decision and the discarded action lets you confirm whether a vanished move was actually a conflict the server resolved against the player. That converts an accusation of the game ate my turn into a precise, defensible record of what the reconciliation did and why.
Notification delivery and player awareness
Asynchronous games live or die by notifications, because a player who is not told it is their turn simply stops playing. Capture the notification state for the turn in question: whether a push was sent, whether the platform accepted it, whether the device registered for notifications, and the last token refresh. A report that a player never knew it was their move usually traces to a notification that was sent but never delivered, or a stale push token, and the captured delivery status pinpoints which. Without it you cannot tell a notification bug from a player who simply did not open the app.
Capture the player's notification settings and the platform delivery receipts where available. A player may have disabled notifications, or the platform may have throttled them, and both look identical to a delivery bug from the outside. Recording the device's permission state, the topic or channel subscription, and any delivery receipt the platform returned separates a configuration problem from a genuine send failure on your side. Since re-engagement depends entirely on these notifications reaching players, treating delivery as a first-class piece of captured state is what keeps an asynchronous game from quietly losing players to silence.
Setting it up with Bugnet
Bugnet's in-game report button can snapshot the asynchronous state when a player taps it. Alongside the device and platform context, the SDK attaches the client's turn number and state version, the server's corresponding values when reachable, the submitted action and its server verdict, the last sync time, and the notification delivery status. Instead of a ticket reading my move disappeared, you receive both sides of the divergence, which often reveals a stale submission or a silent conflict resolution that no description from either player could have surfaced on its own.
Asynchronous bugs frequently affect many games at once when a reconciliation or notification defect ships, so occurrence grouping helps. If a sync bug drops moves across many matches, every affected player files what is really one issue, and Bugnet's grouped count shows the blast radius. Custom fields for the conflict resolution path, the version delta between client and server, and the notification delivery status let you filter the dashboard to, for example, every report where the client was more than one version stale, which isolates the reconciliation failures from ordinary illegal-move rejections so you fix the systemic cause.
Testing asynchronous flows
Teams that ship reliable asynchronous play test the time-separated flows that real players create, not two browser tabs side by side. Simulate stale submissions by having one client act from an outdated state and confirm the server reconciles sanely, force version conflicts and verify your resolution policy never silently loses a move without record, and test notification delivery on real devices including stale tokens and disabled permissions. Each of these maps to a report you would otherwise field weeks after launch, when a player quietly stops playing because the game went silent.
After launch, let the captured state drive triage. Reproduce a lost move by replaying the client and server versions from the report, confirm whether reconciliation or delivery was at fault, and fix the policy or the notification path accordingly. Group reports by version delta and notification status to see whether your problems are mostly sync or mostly awareness, and harden the weaker one. A healthy asynchronous game is one where every turn is reconciled predictably and every player is reliably told to come back, which you ensure by capturing both the state and the notification on every report.
Async bugs are divergences you cannot see live. Capture both sides' versions and the notification status and the desync becomes a clear record.