Skip to main content

Errors

Gateway rejections and GraphQL errors throw typed exceptions: GoliathOperationError is the one to handle in normal application flow — it means the gateway accepted and ran your call, but the operation itself reported errors. An operation can also report an outcome in its successful payload. For example, applyTaskSet.failedStep signals partial completion without a GraphQL error, so it does not throw GoliathOperationError. Check the operation’s documented result fields too.

Retries (built in)

  • Both 429s are pre-execution rejections — retried for any operation, honoring Retry-After when provided; otherwise they use backoff.
  • Network errors, timeouts, and 5xxs are retried only when a re-send cannot double-fire a side effect: queries, or mutations sent with an idempotencyKey.
  • A keyed 409 idempotency_conflict is retried with the same key, within the retry budget, to retrieve the original request’s result.
  • A mutation without an idempotency key is not retried after a network failure, timeout, or 5xx; the pre-execution 429 retries still apply.
  • 402 subscription_inactive is not retried. Restore the subscription in the app; billing and profile recovery reads remain available with normal scopes.
  • Backoff is exponential with full jitter: 500ms base, 8s cap.

Idempotency

Every mutation accepts options.idempotencyKey:
Always pass one on writes. Without it, a timed-out request may already have changed data, and retrying it by hand can double-fire. Passing idempotencyKey to a read is a compile error, matching the 400 the gateway returns at runtime. The key is any string of 1-255 characters (a UUID is the obvious choice). The gateway reserves it before executing and stores the response when the request completes; keys expire after 24 hours.
Detecting replaysWhen a retried write was already executed, the gateway replays the stored response instead of re-running it. Replays surface through the onMeta callback (meta.replayed === true) — including replays whose stored body carries errors.
When a key is handed backA failure that provably happened before the write took effect — bad variables, an invalid phone number, a Do-Not-Contact block — releases the key, so you can correct the request and retry with the same one. A key whose original request is still in flight returns GoliathIdempotencyConflictError (409): retry shortly with the same key to pick up its stored result.