PersistlyPayloadTooLargeError for slotInfo/data values that exceed documented limits.
JavaScript Limits And Errors
Use the JS SDK as if limits and errors are part of the type system.
Good integrations enforce payload bounds, map structured error codes directly, and never assume the runtime is broader than create, load, and sync.
SDK Surface
The SDK should expose typed statuses and typed errors, not force application code to inspect raw HTTP responses.
PersistlyUnauthorizedError when the runtime key is missing, invalid, or for the wrong environment.
PersistlyForbiddenError when an account session cannot access the requested account or slot.
PersistlyNotFoundError when the requested account, slot, or account/slot does not exist in the keyed environment.
PersistlyRateLimitedError when the runtime asks the client to retry later.
PersistlyServerError when Persistly fails internally and the operation result is unknown.
Payload Limits
Keep saves bounded and JSON-shaped.
Current beginner examples should assume 256 KB slot data and 16 KB slotInfo unless the project plan/config says otherwise. Store screenshots, videos, binary blobs, and large base64 payloads outside save data.
Status And Errors
Use PersistlySyncStatus plus typed SDK errors in application code.
import {
PersistlyClient,
PersistlySyncStatus,
PersistlyPayloadTooLargeError,
PersistlyUnauthorizedError,
} from "@persistlyapp/sdk";
const client = new PersistlyClient({
runtimeKey: process.env.PERSISTLY_RUNTIME_KEY!,
});
try {
const result = await client.syncAccountSlot({
accountId,
accountSessionToken,
slotId,
baseVersion: local.version,
slotInfo: local.slotInfo,
data: nextData,
});
if (result.status === PersistlySyncStatus.Accepted) {
local = result.slot;
}
if (result.status === PersistlySyncStatus.Conflict) {
const cloudSlot = result.slot;
// App-specific recovery: keep server data, keep local edits, or merge.
local = await reconcileSlotConflict(cloudSlot, localDraft);
}
} catch (error) {
if (error instanceof PersistlyPayloadTooLargeError) {
console.error(error.code, error.details);
}
if (error instanceof PersistlyUnauthorizedError) {
console.error("Check the runtime key and target environment.");
}
}Common Mistakes
The fastest path to drift is ignoring these constraints.
Do not use playerRef as a public runtime lookup key from shipped clients.
Do not start with raw create/load/sync unless you intentionally need the advanced runtime contract.
Do not compare raw status strings. Use PersistlyGameSaveStatus and PersistlySyncStatus constants.
Do not treat accountSessionToken as an account password or recovery system. The default facade persists it as part of the local game-save identity.
Do not treat transfer codes as passwords, invites, playerRef lookup, support lookup, or long-lived recovery keys.
Do not treat runtime keys as privileged admin secrets.
Do not treat client-written accountData as a payment ledger. Validate purchases in a trusted payment/backend flow first.
Do not invent slot_id semantics at the platform layer; put save-selection labels in slotInfo instead.
Do not ignore canonical sync responses. Replace your local canonical snapshot after every create, load, or sync.
Do not sync every frame or use Persistly for real-time PvP data.