Quick answer: In a networked game a bug can live on the client, on the server, or in the disagreement between them, and you cannot fix it until you know which. Isolate by capturing both sides and asking what the authoritative server actually did versus what the client showed. If the server state is correct and the client is wrong, it is a client bug; if the server itself is wrong, it is a server bug.

When something goes wrong in a networked game, the very first question is not how do I fix it but where does it live. A player reports their shot did not register, or an item vanished, or an enemy teleported. That single symptom could be a client rendering the wrong thing, a server processing input incorrectly, or the two simply disagreeing across the network. Spend hours fixing the client when the bug is server-side and you have wasted the day. This post is about that prior question: how to isolate which side a networked bug actually lives on by capturing both ends and comparing them against the one source of truth, the authoritative server.

The authoritative server is your ground truth

In most networked games the server is authoritative: its version of the world is the truth, and the client is a prediction and a display of that truth. This is the key to diagnosis, because it gives you a reference to compare against. When a player reports something wrong, the question becomes precise: what did the server actually compute, and what did the client show? If the server's state was correct and the client displayed something different, the bug is on the client. If the server itself computed the wrong thing, the bug is on the server. The authoritative state turns a vague symptom into a decidable question.

Without that framing, networked bugs feel hopelessly ambiguous, and people guess, usually blaming whichever side they understand less well. With it, diagnosis becomes a procedure: establish what the truth was, compare each side to it, and the disagreement points at the culprit. The client predicting a hit that the server correctly rejected is a prediction or reconciliation bug on the client. The server rejecting a hit that should have landed is a server logic bug. Same symptom, opposite sides, and the only way to tell them apart is to look at what the authority actually decided.

Capture both sides, tagged to line up

You cannot compare client and server unless you captured both, and you cannot compare them unless they share a coordinate system. Tag every relevant message and state snapshot with a sequence number and a tick or timestamp so you can line the two logs up afterward. When the player reports the shot that did not register, you want to find the exact tick on both sides: what the client sent, what the server received and when, what the server computed, and what it sent back. Lining those up shows you precisely where reality diverged from what the player saw.

Capture state, not just events. Log the position, health, and relevant variables on both sides at the moment of the symptom, because the disagreement is usually a single field that differs. Often the revealing detail is timing: the client fired at tick 100 based on where it saw the enemy, but the server had already moved that enemy by the time the input arrived, so it correctly registered a miss. That is not a bug at all, it is lag compensation working, or failing, and you can only see it by having both timelines side by side with a shared clock.

Reproduce on each side in isolation

Once you suspect a side, try to reproduce the bug with the other side taken out of the equation. If you think it is a client display bug, can you feed the client a known, correct server state and see if it still renders wrong? If yes, the server is exonerated and you have your answer. If you think it is server logic, can you feed the server the exact input sequence in isolation, without any client, and see it produce the wrong result? A bug that reproduces with one side removed clearly lives on the side that remains.

This isolation is also how you avoid the most common diagnostic trap: fixing a symptom on the wrong side. It is entirely possible to paper over a server bug with a client-side workaround that makes the symptom go away while leaving the real fault in place, where it will resurface in another form. By reproducing each side independently you confirm not just that your fix works but that you fixed the actual source. A bug you cannot reproduce in isolation on either side usually lives in the network interaction itself, which is its own category and a sign to look at timing and ordering.

Watch for the network-in-between case

Sometimes neither the client nor the server is individually wrong, and the bug lives purely in their interaction: a message lost, reordered, or delayed by the network produces a state that neither side would have reached alone. The client did the right thing with what it knew, the server did the right thing with what it received, but what it received was incomplete or out of order. These are the trickiest bugs because each side, examined alone, looks correct, and only the comparison of the two timelines reveals that they were working from different information.

Diagnosing these requires looking at the wire, not just the endpoints. Did every message the client sent actually arrive at the server, and in order? Did an acknowledgment get lost so the client retried or gave up? The fix for an in-between bug is usually not in either side's logic but in how they handle imperfect delivery: better acknowledgment, sequencing, or reconciliation. Recognizing that a bug is in-between rather than on one side saves you from endlessly auditing client and server code that is each individually correct, and points you at the protocol where the real problem lives.

Setting it up with Bugnet

The hard part of telling a server bug from a client bug is usually getting the context, and Bugnet captures it automatically. When a player hits the symptom and taps the in-game report button, the report arrives with their state, platform, build, and player attributes, so you start from concrete data about what the client saw rather than a vague description. For crashes, the stack trace tells you immediately whether the failure was in client code or, if you report server crashes through the same pipeline, in server code, which is often the first and fastest cut between the two sides.

Occurrence grouping then helps you read the population. A bug that only the client crashes on, with a client-side stack trace, grouped across many players, is plainly client-side; a fault that shows up as a server crash signature is server-side. Custom fields let you record which side you isolated the bug to and the diverging tick you found, keeping the diagnosis attached to the issue. Player attributes let you check whether the symptom concentrates on one platform, a strong hint that it is a client bug. One dashboard holding both the client reports and the server crash stream is exactly the both-ends view this diagnosis depends on.

Make the habit pay off

Once you have isolated a bug to a side, write down how you knew, because the same symptom will recur and the diagnostic shortcut is worth saving. Over time you build a catalog: this kind of symptom with the server state correct is always a client prediction issue, that kind with a specific server log is always this server path. The catalog turns slow forensic work into fast pattern matching, and it lets less experienced teammates diagnose networked bugs without rediscovering the whole method each time from scratch.

Most importantly, resist the urge to guess. The single biggest time sink in networked debugging is confidently fixing the wrong side because guessing felt faster than capturing both ends. The discipline of always establishing what the authoritative server actually did before touching any code feels slower on the first bug and is dramatically faster across all of them. Knowing where a bug lives is half of fixing it, and in a networked game that knowledge comes only from comparing both sides against the truth, every time, no matter how obvious the answer seems.

Knowing where a bug lives is half of fixing it. Compare both ends against the authoritative server before you change a single line of code.