Error reference
Every failure is a TriggairError with
{ code, message, agentHint, requestId }. The
agentHint tells you how to fix the call; each code below links
to its full fix.
- bad_request (400)
The request was malformed — a missing/invalid field, a bad slot/board/key name, or non-JSON body.
- unauthorized (401)
No valid credential. A game-scoped call needs the publishable key; a player-scoped call also needs a player token.
- forbidden (403)
Authenticated but not allowed — e.g. a banned player, or Turnstile is required for a new anonymous player.
- cors_forbidden (403)
The browser Origin isn't in the game's allowed_origins. The classic 'works locally, 403s once deployed' trap.
- game_suspended (403)
A Triggair operator has suspended this game (a Terms-of-Service or abuse review). A valid key still resolves, but no game-scoped call proceeds.
- conflict (409)
The action conflicts with current state — e.g. a handle already taken, a friendship you've blocked, or a daily reward already claimed today.
- save_conflict (409)
An optimistic-concurrency (OCC) save conflict: the slot's version changed since you read it (a lost race or a stale If-Match).
- not_found (404)
The resource doesn't exist for this caller — an empty save slot, an unconfigured/disabled board, or a game/id you don't own.
- payload_too_large (413)
The body exceeds a limit — a save > 256 KB, a config > 64 KB, or a share context > 4 KB.
- quota_exceeded (402)
A plan limit was hit — save slots (3 on free), the monthly-active-player cap, or another metered ceiling.
- insufficient_funds (402)
A wallet spend was denied because the balance would go negative. Balances never go negative — the whole transaction rolled back (you did not spend and fail to receive).
- unknown_currency (400)
A grant or spend referenced a currency that isn't defined for this game. Currencies are explicit definitions — there is no implicit create.
- unknown_item (400)
A grant, consume, or store listing referenced an item that isn't in the game's catalog. Items are explicit definitions — there is no implicit create.
- insufficient_item (409)
A consume/spend asked for more of an item than the player owns. Inventory quantities never go negative — the whole transaction rolled back.
- store_limit_reached (403)
The player already bought this listing up to its per-player purchase_limit.
- out_of_stock (409)
The store listing's global stock is exhausted.
- loot_not_enabled (403)
This loot table isn't live — it hasn't been enabled with the required compliance acknowledgement (loot boxes touch gambling/age regulation).
- out_of_energy (403)
The player doesn't have enough energy/lives for this action. Energy regenerates over server time (never the client clock).
- item_not_tradable (403)
This item can't be gifted — only items defined as tradable move between players.
- flag_not_found (404)
No active feature flag with that key (it's undefined or turned off). Unknown flags are expected — the SDK resolves them to the caller's safe default.
- segment_definition_invalid (422)
A segment's rule tree failed validation — an unknown predicate/operator, a bad value type, or too deep/large a tree.
- code_invalid (404)
No promo code with that string exists in this game (typo, or a never-minted code).
- code_expired (410)
The code's redemption window has closed (server time), or the code/campaign is disabled.
- code_already_redeemed (409)
This player already redeemed this code (per-player limit reached).
- code_campaign_exhausted (403)
The campaign hit its total redemption cap — no more rewards remain.
- code_wrong_audience (403)
The code is restricted to a player segment this player isn't a member of.
- quest_not_complete (409)
A quest was claimed before its objectives were met. Progress is a server-side projection over the stat store — the client can't assert completion.
- tournament_not_open (409)
A join was attempted before the tournament's registration window opens (server time, §4.10).
- tournament_closed (409)
The tournament has ended — joins and submissions are closed. Prizes (if any) are already in the winners' inboxes.
- tier_not_earned (403)
A battle-pass tier was claimed before the player earned enough battle points to reach it.
- premium_required (403)
A premium-lane battle-pass reward was claimed but the player doesn't own the premium pass.
- not_your_turn (409)
A turn was submitted to an async match when it wasn't that player's turn.
- async_conflict (409)
An async-match turn lost the optimistic-concurrency check — the `version` didn't match the current one (another turn landed first).
- team_forbidden (403)
The player's team role doesn't permit this action (or they aren't a member) — e.g. a non-admin kicking, a non-owner disbanding, or the owner trying to leave.
- team_full (403)
The player is already in the maximum number of teams allowed.
- team_banned (403)
The player is banned from this team (by an admin/owner) and cannot join by any path — open join, invite-accept, or request-approve.
- storage_conflict (409)
An optimistic-concurrency write to a storage document lost the race — the `If-Match` version didn't match the current one (the multi-tab/multi-device lost-update guard).
- storage_forbidden (403)
A player token tried to write a storage document its policy doesn't allow — e.g. authoritative shared/world state (write_policy: server, the fail-closed default).
- already_reported (409)
This reporter already has an open report against the same target.
- report_rate_limited (429)
This player filed too many reports within the hour (per-player abuse control).
- player_banned (403)
This account or device is banned from the game, so no player token is issued.
- appeal_already_decided (409)
This ban's appeal was already granted or denied.
- age_unknown (403)
This player's age bracket isn't established, so every regulated feature (loot boxes, real-money IAP, open chat, public UGC) fails closed to the most-restrictive treatment.
- age_restricted (403)
This feature isn't available to this player's age group in their region, and no parental consent can unlock it.
- parental_consent_required (403)
A minor may use this feature only with verifiable parental consent (VPC), which hasn't been requested yet.
- consent_pending (409)
Parental consent has been requested for this minor but the parent hasn't decided yet.
- rate_limited (429)
Too many requests — the global token bucket or a per-board submission cap. A `Retry-After` header (and X-RateLimit-*) tells you when.
- internal (500)
An unexpected server error. Rare and transient.