Skip to main content

Operations

EventMinimumRecommended
After serverWithLeastClients1.0 s1.5 s
After first actor registration0.2 s0.5 s
Actor heartbeatevery 4 s
Any client trafficevery 60 s

Common error codes

Delivered as GENERIC_ERROR_MESSAGE (type 3) with echoed sequence. Names below match the current wire enum; the MAP_* forms are legacy aliases.

CodeNameTypical cause
5INVALID_TOKENMalformed token material, or not a valid app-scoped token
6APP_NOT_FOUNDUnknown app (formerly MAP_NOT_FOUND)
7UNAUTHORIZEDPermission denied — no active app access / tier permission, or no grid permission for the target chunk (see Permissions below)
13GAME_TOKEN_WRONG_SIZEMalformed token material
15INVALID_REQUESTWire layout or field error
18INVALID_APP_IDNot authorized for this app — unknown app or the token is scoped to a different app (app-scope mismatch)
20USER_NOT_AUTHENTICATEDSession not ready (or not an app-scoped token) — mintAppToken, call serverWithLeastClients, wait ~1.5 s, retry
32TOKEN_EXPIREDThe app-scoped token passed its expiresAt — Buddy evicted the session. Mint a fresh token (refreshAppToken for the same app) and re-assign

Permissions (always enforced)

Every spatial message is authorized on the server. The sender must have active app access whose tier includes the relevant permission key (access to move/send events, update_voxel_data to edit voxels, use_voice_chat for audio) and the target chunk must be inside a grid where the sender holds that key. A message failing either check is dropped and answered with GENERIC_ERROR_MESSAGE / UNAUTHORIZED (code 7).

New apps are open by default — they ship with a default tier granting all permissions and a world-spanning default grid, and granting a player app access automatically grants them all grid permissions — so out of the box any entitled player can act anywhere. App owners opt into restrictions (safe zones, plot ownership) via the Game API. See Game API → Permissions overview and Grids and permissions.

The first message to a brand-new chunk region may briefly return UNAUTHORIZED while the server loads that region's grid permissions; retry and it succeeds.

Permission denials are transient and self-healing in general: the server periodically re-pulls a denied session's cached permission state (a few seconds of backoff between refreshes), so an entitlement granted after you connected — or one that reached the game database late — starts working without re-authenticating or reassigning. If you receive a stream of UNAUTHORIZED replies, keep sending at a reduced rate for ~10-15 seconds before falling back to a fresh serverWithLeastClients assignment.

App suspended or over budget

If an app is runtime-denied — suspended, out of wallet funds, or over a spend cap on the shared environment — the server refuses to authorize its game tokens, so session setup fails and spatial sends come back UNAUTHORIZED / USER_NOT_AUTHENTICATED. This is a billing/runtime state, not a client bug: resolve it on the management API (fund the wallet, raise the cap, or renew). See Shared environment & billing.

Server reassignment

If Buddy restarts, evicts your session, or you need a different host:

  1. Call serverWithLeastClients on the Game API again (refreshAppToken first if the app token is near expiresAt).
  2. Wait ~1.5 s for the session to be ready.
  3. Resume UDP with the same app-scoped token on the new host and clientPort.

Load shedding — COMMAND_RECONNECT (type 22)

A server protects itself when it runs hot. If a CPU core or system memory stays high for several seconds, the server reports NearCapacity (so the Game API stops sending it new clients) and, if pressure continues, Full — at which point it sheds some existing clients to recover. A shed client receives a small server→client datagram:

[1B type=22][32B HMAC]

The 32-byte HMAC is HMAC-SHA256 keyed on your 64-octet app-scoped token (the same token you use to sign your spatial messages) over the single type byte. Because only you and the server hold that token, a matching HMAC proves the command came from the server — verify it and ignore the datagram if it does not match. When you receive a valid COMMAND_RECONNECT, follow the Server reassignment steps above: re-query serverWithLeastClients (it will not return the overloaded server) and move your session to the returned host. The losing server keeps serving you for a short grace period (≈5 s) and then deletes your session and ignores further packets, so reconnect promptly. There is no reply to send, no sequence number to echo, and no reason field; it is a one-shot directive.

Native (direct-UDP) clients should verify the HMAC and handle type 22. Browser clients using the GraphQL UDP proxy are moved automatically by the proxy (which verifies the HMAC) and never see this message.

Browser clients

Use the GraphQL UDP proxy instead of raw UDP.