Error handling
Catch PlotError when your game can offer a
useful retry or exit choice. Every Plot failure exposed as an error inherits
from this class and has a stable lowercase code:
Use the exported PlotErrorCode values for
program logic. The human-readable message is for developer diagnosis and may
change. Do not parse it or show it directly to players. An optional cause may
help diagnostics, but only code is a stable failure field.
Error types
PlotConnectionErrormeans the connection stage ofPlot.ready()or its connection settings failed.PlotOperationErrormeans startup synchronization or a gameplay operation failed.PlotNotReadyErrormeans a readiness-dependent API—such as a state read or write, clock read, or channel send—was used before Plot installed the complete ready state. Its code isnot-ready.
All three inherit from PlotError; most games need only the base class.
instanceof remains reliable if a bundle contains more than one SDK copy.
Invalid arguments and values rejected by the SDK's local validation use
JavaScript's TypeError. These are code defects to fix, not service problems
to retry. Examples include an invalid player ID, unsafe time value, malformed
parentOrigin, or channel payload containing a Date. If Plot rejects a value
after submission, it reports a PlotError such as invalid-value instead.
How failures are reported
Subscriptions can be registered before readiness. Optional
Plot.connection diagnostics are also
available during startup. Pre-registered initial snapshot callbacks run after
the complete ready state is installed but just before ready() resolves, so
reads, writes, sends, and time are available inside them.
Codes and recovery
These are the current PlotErrorCode values.
Repeat an action only when it is still meaningful and its outcome is known.
Only an explicit Plot.ready() starts readiness; another SDK call never does
so implicitly. Repeated calls are safe and share one attempt. A call that
supplies parentOrigin must match any setting already in use; omitting it
reuses the current setting. A failure with
connection-failed, connection-timeout, readiness-timeout, or
communication-failed clears that attempt, so a later explicit call on the same
page can retry. Other startup failures are retained for that setup. Invalid
options and connection-options-mismatch reject only the incorrect caller.
incompatible-sdk, launch-denied, participation-ended, and session-ended
are terminal for the current launch. Plot adapts SDK releases that remain in its
support window, so an incompatibility requires republishing with a supported
version.
For Plot.showSystemUi(), operation-timeout means the panel may already have
opened before its confirmation was lost. Do not automatically retry it. A
service-unavailable result can also mean Plot suppressed a rapid repeat
request; leave the current game UI usable instead of looping until the panel
opens.
Plot.party.getJoinUrl() is read-only, so its operation-timeout has no hidden
party mutation or UI side effect. You may retry deliberately once the runtime is
connected and the URL is still needed. Each attempt asks Plot for the current
authoritative URL.
The session ends for everyone when the host leaves or closes the party, or when the host ends the game. A game does not clear synchronized objects itself and must not expect that ended session's state in a later launch.
For synced audio, pause, stop, and a replacement cue may
intentionally reject an earlier pending play/resume with operation-cancelled.
That cancellation does not populate the object's error or emit onError.
Initial operational failures both reject the method promise and notify onError;
choose one path for player-facing messages. Later playback failures arrive through
onError and the snapshot because a resolved promise cannot reject again.
Never blindly retry an unknown write
If gameState.set(), gameState.update(), playerData.setSelf(), or
playerData.updateSelf() reports operation-timeout, the change may have been
accepted even though its confirmation never reached the game. Repeating it
could apply the intent twice.
Keep rendering the latest cached snapshot. Reconcile with a later ordered
onChanged() event or a subscribe() callback with reason: 'resync', then
decide whether the intended change is still needed. Plot does not expose a
forced-resync method or turn an unknown outcome into success.
Cached state and connection status
Use the connected lifecycle callback to reconcile
all state together. Plot.connection.recovery reports known missing reliable
ranges through replayGap and identifies crash-restored state through kind.
Checkpoint recovery
can also lose later messages with no saved gap position; a null gap does not
prove complete history after a crash. A replay gap
does not itself make synchronized state unusable. Completed planned updates
preserve accepted state and unexpired history; unexpected crashes can roll back
to a periodic snapshot.
After readiness, party, Game State, and Player Data getters keep returning the
latest cached snapshots during a temporary interruption; those values may be
stale. Plot.time continues advancing from its latest synchronized anchor.
Plot holds a bounded amount of recoverable work while restoring current
synchronized state. In the same running page, the original readiness promise
stays complete and Plot restores the connection without another ready() call.
A temporarily unavailable service can leave that page disconnected and
gameplay paused; Plot tries a fresh synchronization when the service reconnects.
A refreshed iframe is a new page and calls ready() during normal startup.
If recovery fails irreparably, the original ready() promise stays resolved;
calling it again does not reopen that SDK instance. Later valid party and state
reads, state writes, and channel sends report the retained
PlotOperationError. Reload the game page or exit rather than building a
second readiness or reconnect loop. Connection diagnostics and the last
synchronized clock anchor remain available for UI and logging.
Use Plot.connection only for an
offline indicator or to delay a deliberate retry. disconnected means Plot
cannot currently exchange synchronized realtime data. It may represent
temporary recovery or a terminal failure, so use the failed operation's error
to decide what recovery is possible. Ordinary game code does not open or manage
the underlying realtime connection or a reconnect loop.
Plot.realtime.latest reports a separate optional transport. If its available
field becomes false, replaceable samples are dropped while synchronized state
and reliable events can stay connected. Pause cosmetic high-rate sends as needed;
do not treat this status alone as a reason to stop shared gameplay.
Keep player copy friendly
Log the error name, code, message, and stack through your development logging. Do not include credentials, personal data, or secret game material.
Write player-facing text around the next useful choice—for example, “Plot lost contact with this game. Try again or return to the party”—instead of exposing a technical SDK message.