Skip to content

Error codes

system.error messages carry a stable code and a human-readable message. The codes below are part of the protocol’s public surface — renaming or removing one is a breaking change.

CodeCause / remediation
session_not_foundThe session code does not exist (or its 4-hour TTL expired). Controller should prompt the user for a new code.
session_fullThe session has reached its maximum player count. Currently uncapped at the relay, reserved for future per-tier limits.
invalid_codeThe code is not a valid 4-character format. Most often a typo on the controller side.
rate_limitedToo many requests too fast. Back off and retry. Check the client SDK error path before retrying — abusive clients are dropped.
protocol_version_mismatchClient and relay disagree on PROTOCOL_VERSION. Update the SDK on the host side.
malformed_messageThe message did not parse as a valid ProtocolMessage. Almost always a custom client emitting bad JSON.
player_not_foundHost called SendToPlayer (or similar) with a player_id that is not currently connected. Check manager.Players first.
host_resume_rejectedHost tried to resume a session whose host_id doesn’t match the durable record. Falls through to fresh allocation.
stale_inputController emitted input.widget_event for a screen they are no longer on. Relay drops the event and increments pairkit_stale_input_total.
screen_not_foundHost pushed a screen.show for a screen name that does not exist in the registered flow.
revision_conflictHost’s screen.update_data revision is older than what the player already has. Relay drops the patch.
player_offlineSent in response to operations targeting a disconnected player (e.g. PromptAsync mid-flow).
request_cancelledA control.request was cancelled before the controller responded. Surfaces as OperationCanceledException on the host.
internal_errorUnexpected server-side error. Investigate via Sentry.
unauthorizedAPI key was missing, malformed, or revoked. Get a key at app.pairkit.dev and paste it into PhoneControllerManager. Returned only when the relay runs in strict mode (PAIRKIT_RELAY_OPEN_MODE=false).

Handling errors in game code

The Unity SDK surfaces every system.error via PhoneControllerManager.OnError. Most errors are advisory (e.g. stale_input) and do not require host action. The exceptions:

  • host_resume_rejected — the SDK’s CloudRelayTransport falls through to fresh allocation automatically. Game code typically does nothing.
  • player_not_found — your SendToPlayer targeted a disconnected player. Check manager.Players before sending.
  • internal_error — investigate. Sentry has the relay-side stack.

For local-relay (LAN mode) sessions the same codes are emitted by the in-process relay.