PlayMesh/Docs
HomeGitHubnpm

Connection & Reconnection

The client connection lifecycle - connect, auto-reconnect, token refresh, errors, and kicks.

Connecting

connect() resolves once the server has fully established the session - after your authentication hook ran and admission placed the session in its initial instances. It rejects if the server refuses the connection - with a PlayMeshError carrying a machine-readable code - and throws if the client is already connected or connecting.
const client = new PlayMeshClient({ url, auth: { token } });

try {
  const session = await client.connect();
  // session: { id, userId, roles, instances }
} catch (error) {
  // error.code tells you why - never match on the message text
  if (error.code === 'VERSION_MISMATCH') showUpdatePrompt();
  else if (error.code === 'AUTH_FAILED') showLogin();
  else showError(error.message);
}
disconnect() tears the connection down and clears client.session. A later connect() starts fresh.
ℹ
The client announces its wire-protocol version during the handshake. PlayMesh 0.7 speaks wire protocol v3: a mismatch (e.g. a 0.6.x client against a 0.7.0 server) is rejected on both sides with code VERSION_MISMATCH - upgrade @playmesh/server and @playmesh/client together.

Error codes

Every error carries a code: ServerError.code in onError, and error.code on rejected connect(), join() and requestTo() promises. Servers may also send their own application codes (thrown as PlayMeshError).
Method / PropertyDescription
VERSION_MISMATCHconnect(): client and server speak different wire-protocol versions.
AUTH_FAILEDconnect(): the authentication hook rejected the connection.
USER_CONNECTEDconnect(): uniqueUser 'reject' and the user already has a live session.
CONNECTION_FAILEDconnect(): a connection-setup hook threw - the message is the server's real error.
SIGNING_REQUIREDconnect(): signing mismatch between client and server.
JOIN_DENIED / ROLE_REQUIREDjoin(): the join was vetoed, or the instance needs a role you lack.
RATE_LIMITEDonError / onKick: an event exceeded the server's rate limit.
TIMEOUTrequestTo(): no response in time (client-side).
DISCONNECTEDAny pending call: the connection dropped first (client-side).
LEFT_INSTANCErequestTo(): you left the target instance before the response arrived (client-side).

Automatic reconnection

Reconnection is handled by the underlying Socket.IO client and is on by default. Tune it through the socket option:
const client = new PlayMeshClient({
  url: 'https://game.example.com',
  socket: {
    reconnection: true,
    reconnectionDelay: 1000,
    reconnectionDelayMax: 5000,
    reconnectionAttempts: Infinity,
  },
});
On every reconnect the server re-authenticates and re-admits the session, and the client re-seeds its instance list, presence, and synced-state replicas from the new join snapshots. Pending requestTo() promises reject on disconnect - they are never silently replayed.

Token refresh

Pass auth as a function and it is re-evaluated on every connection attempt - so an expired token is refreshed before each reconnect instead of failing the handshake:
const client = new PlayMeshClient({
  url: 'https://game.example.com',
  auth: async () => ({ token: await authService.getToken() }),
});

Lifecycle handlers

client.onDisconnect(reason => {
  showReconnectOverlay(reason);
});

client.onReconnect(() => {
  hideReconnectOverlay();
});

client.onError(error => {
  // { scope: 'connection' | 'event' | 'join' | 'chat',
  //   code, event?, instance?, message }
  if (error.code === 'RATE_LIMITED') slowDown();
  if (error.scope === 'connection') showAuthError(error.message);
});

client.onKick((reason, code) => {
  // Told why, then force-disconnected - no automatic reconnect makes sense here
  // code: 'KICKED', 'REPLACED' (signed in elsewhere), 'RATE_LIMITED', or an app code
  showKickedScreen(reason, code);
});
ℹ
error.scope tells you what failed: connection (setup/auth), event (an emit was rejected server-side), join (a client.join() was vetoed - error.instance names the instance), or chat (a message was blocked).

Serialization

JSON is the default wire encoding. Set serialization: 'msgpack'to use binary msgpack frames (usually noticeably smaller for game traffic). It must match the server's serialization option - a mismatched client cannot connect.
const client = new PlayMeshClient({
  url: 'https://game.example.com',
  serialization: 'msgpack', // server: new PlayMesh({ serialization: 'msgpack' })
});

Reconnection with signing

With signing enabled, every connection gets a fresh session nonce from the server. After a reconnect the client waits for the new nonce before sending signed events; events queued for the old connection are dropped and reported via onError rather than replayed. See Auth & Admission for the full signing model.