Skip to main content
Every API, network and local failure is one type: *squarecloud.APIError. Inspect it with errors.As. The shorter snippets below run inside the program from Running the examples: paste one at a time into main and run goimports.

APIError

Unwrap() returns the cause (the transport, decoding or context error) for NETWORK_ERROR, TIMEOUT and invalid JSON, or nil. Error() renders squarecloud: <METHOD> <path>: HTTP <status> <CODE>: <message>, without HTTP <status> when the status is 0 and without : <message> when it is empty. Match on the fields, not on this text.

Canceled and expired contexts

A call whose ctx is canceled returns an *APIError with NETWORK_ERROR, and one whose deadline passes returns TIMEOUT, both with status 0. They unwrap to the context’s error:
A few failures are not *APIError:
  • Realtime.Next returns the bare ctx.Err() when its ctx ends, and io.EOF when the stream ends normally.
  • Caller-side problems are plain errors: a nil upload reader, a snapshot URL or base URL that cannot be parsed, an input encoding/json cannot encode, and an error of the io.Writer passed to DownloadSnapshot.

SDK codes

Code* constants

Code is a plain string. The package has one constant per public API code, named after it in Go style (CodeAppNotFound for APP_NOT_FOUND, CodeInvalidID, CodeDNSFailed, …), plus the SDK’s own codes above. CodeRateLimit (RATE_LIMIT) and CodeRateLimitExceeded (RATE_LIMIT_EXCEEDED) are still exported, marked deprecated: the API now answers RATE_LIMITED (CodeRateLimited) for both. The list of API codes grows. Handle an unknown code by its HTTP status:

API error codes

Every other code comes from the API. The API error reference lists each one with its HTTP status, meaning and fix, and each SDK page lists the codes its methods return most often. Any call can also answer 401 ACCESS_DENIED (a bad key), 403 MISSING_SCOPE or RESOURCE_NOT_ALLOWED (the limits of the key), 429 (see Rate limits) or 503 DATABASE_UNAVAILABLE. AI.Chat errors use lowercase OpenAI codes instead (access_denied, rate_limit_exceeded, server_overloaded, …), which Code carries verbatim. See AI.

Retries

The SDK only retries what is safe to repeat, up to WithMaxRetries times (default 2, so up to 3 attempts): It never retries:
  • TIMEOUT;
  • any 429: RATE_LIMITED can be a block of about 30 minutes, and KEEP_CALM is not retried either;
  • other 5xx;
  • AI errors.
503 DATABASE_UNAVAILABLE can arrive after a mutation was already applied, so the SDK does not retry it outside GET. Retry your own idempotent mutations if you need to. An upload is retried only when its body can be replayed: an io.ReaderAt with a known size, such as an *os.File (see Commit and upload). The wait before retry n (starting at 0) is min(8 s, 500 ms · 2^n) · U(0.5, 1): exponential backoff with 50% to 100% jitter. Set WithMaxRetries(0) to turn retries off.

Timeouts

WithTimeout (30 s) applies only when ctx has no deadline, and one deadline covers the whole call, retries and backoff waits included. See Timeouts for the calls with a 2-minute floor and the calls with no default deadline. A deadline that passes returns TIMEOUT with status 0, is never retried, and unwraps to context.DeadlineExceeded.

Rate limits

Every account has a limit of requests per 60 seconds, set by its plan (values), and some routes have their own:
  • 429 RATE_LIMITED: the account or API key went over its request budget and is blocked for about 30 minutes, or an IP that keeps sending invalid keys is blocked for a short period. Also the limit of the network endpoints and Account.Snapshots.
  • 429 KEEP_CALM: too many calls to one route in a short time.
The SDK never retries a 429. Slow down, and wait before trying again.

Next steps

API error reference

Every error code, with its meaning and fix.

Limits and restrictions

The request limits of each plan.