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.
| Code | Cause / remediation |
|---|---|
session_not_found | The session code does not exist (or its 4-hour TTL expired). Controller should prompt the user for a new code. |
session_full | The session has reached its maximum player count. Currently uncapped at the relay, reserved for future per-tier limits. |
invalid_code | The code is not a valid 4-character format. Most often a typo on the controller side. |
rate_limited | Too many requests too fast. Back off and retry. Check the client SDK error path before retrying — abusive clients are dropped. |
protocol_version_mismatch | Client and relay disagree on PROTOCOL_VERSION. Update the SDK on the host side. |
malformed_message | The message did not parse as a valid ProtocolMessage. Almost always a custom client emitting bad JSON. |
player_not_found | Host called SendToPlayer (or similar) with a player_id that is not currently connected. Check manager.Players first. |
host_resume_rejected | Host tried to resume a session whose host_id doesn’t match the durable record. Falls through to fresh allocation. |
stale_input | Controller emitted input.widget_event for a screen they are no longer on. Relay drops the event and increments pairkit_stale_input_total. |
screen_not_found | Host pushed a screen.show for a screen name that does not exist in the registered flow. |
revision_conflict | Host’s screen.update_data revision is older than what the player already has. Relay drops the patch. |
player_offline | Sent in response to operations targeting a disconnected player (e.g. PromptAsync mid-flow). |
request_cancelled | A control.request was cancelled before the controller responded. Surfaces as OperationCanceledException on the host. |
internal_error | Unexpected server-side error. Investigate via Sentry. |
unauthorized | API 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’sCloudRelayTransportfalls through to fresh allocation automatically. Game code typically does nothing.player_not_found— yourSendToPlayertargeted a disconnected player. Checkmanager.Playersbefore 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.