Troubleshooting
The most common native-UDP problem is "my datagrams send fine but I never receive anything back." Because UDP is fire-and-forget, a send call succeeds even when the packet is black-holed or rejected — so silence is the only symptom. Work down this checklist in order.
"Data goes out, nothing comes back"
1. Did serverWithLeastClients actually succeed?
This query installs your Buddy session as a side effect — see
Authenticate and assign. If
it returns GraphQL errors, the resolver never ran and no session exists, so
every subsequent UDP datagram is dropped.
A frequent cause is requesting a field that isn't exposed (e.g. peerPort), which
fails the whole query. Request only valid fields and log the full response:
query { serverWithLeastClients { ip4 ip6 clientPort status clients } }
Confirm the response body has no errors and a server object with
status: "ReadyForClients".
2. Did you wait after assignment?
Session install is asynchronous. Wait ≥ 1.5 s after serverWithLeastClients
returns before your first UDP send. Earlier messages are silently dropped. See
Operations → recommended waits.
3. Are you sending to the right address and port?
- Send to
ip4onclientPort(typically9091). Prefer IPv4 — see Choosing an address. - A black-holed IPv6 route is a classic cause of "sends succeed, nothing returns."
If you addressed
ip6, switch toip4. - Spatial traffic goes to the client port, never the peer port.
4. Is your HMAC key correct?
This is the single most common client bug. The token is a 64-character string used directly as 64 octets — do not hex-decode it. Hex-decoding produces a 32-byte key and every message fails. See HMAC.
const key = Buffer.from(token, 'latin1'); // 64 bytes — correct
// const key = Buffer.from(token, 'hex'); // 32 bytes — WRONG, will fail
Also confirm:
containsAuth = 1on your first (and every authenticated) message.- The
gameTokenIdin the message tail matches the one from your app-scoped token (themintAppToken/exchangePortalCoderesponse) — not the identity session token fromlogin/register, which Buddy rejects. - The HMAC message is
prefix || token_octets(the token bytes are appended again after the header+payload).
5. Are you listening on the same socket you send from?
Buddy replies to the source address/port of your datagrams. If you send from one socket and try to receive on a different one (or a different local port), the replies never reach your handler. Use one socket for both directions, and accept datagrams from the Buddy host IP regardless of the exact source — a server may reply from a different internal interface than the one you addressed.
6. Is the other player allowed to receive it?
From replication server v0.43.0, some traffic is dropped at the receiver, silently, and the sender
hears nothing: communication between two players when either has blocked the other (movement and
world edits still pass); voice, video, text or a direct message to a player who lacks the matching
permission key (use_voice_chat, use_video_chat, use_text_chat, use_direct_messages); voice
and video that the two players' settings do not admit; and a direct message to a player under 18.
If one receiver gets nothing while others do, check that player's tier keys and
myCommSettings. Voice or video sent with its send setting off, a minor's direct message and a
send under another player's actor are refused instead, with UNAUTHORIZED (7). See
Voice, video, contacts and blocks.
7. If everything above checks out — it's server-side
If you have a clean serverWithLeastClients (no errors, ReadyForClients), waited,
are sending HMAC-valid ACTOR_UPDATE_REQUEST_2 to ip4:clientPort, and listening on
the same socket — and still get nothing — the problem is in the environment, not your
client. Report it to your platform contact. Known server-side causes that produce
this exact symptom:
- Buddy's heartbeat is stale (it isn't registered as
ReadyForClients). - The game-api process is missing a required secret and can't complete the session-install packet.
- A version/routing mismatch between game-api and Buddy.
Error codes
If you receive a GENERIC_ERROR_MESSAGE (type 3) you are at least getting a reply —
decode the error code and see
Operations → common error codes.
INVALID_TOKEN (5) almost always means the HMAC key was hex-decoded (step 4).
INVALID_APP_ID (18) means the token is for a different app (app-scope mismatch)
or you assigned with the session token — re-mint for the correct app.
TOKEN_EXPIRED (32) means your app-scoped token passed its expiresAt and Buddy
evicted the session — mint a fresh one (refreshAppToken for the same app) and
re-run serverWithLeastClients.
USER_NOT_AUTHENTICATED (20) means the session isn't installed yet (steps 1–2)
— or the app is runtime-denied (suspended / out of wallet funds / over a
spend cap), in which case the server won't authorize the token until the studio
resolves it on the management API. See
Operations → app suspended or over budget.
Browser clients
If you cannot open raw UDP sockets, none of the above applies — use the GraphQL UDP proxy instead.