Skylark Models

Errors

Every failure carries a stable code. Switch on that, never on the message.

Every failure returns the same envelope, plus a Retry-After header where a retry makes sense:

{ "error": "human-readable prose", "code": "credits_exhausted", "retryAfter": 30 }

code is the contract. The error prose is written for humans and will change, so a client that matches on it will break. Every shipped SDK switches on code.

One case surprises people: a video job that fails does so inside a 200. The job was accepted, polled, and finished unsuccessfully — so the HTTP status describes the poll, and the failure arrives as result.error.code.

Codes

These statuses are verified against what the handlers actually write. A few codes answer with more than one, which is noted inline — that reflects a real inconsistency in the service rather than an omission here.

CodeHTTPMeaningWhat to do
bad_request400, 404, 405The request was malformed or a field was missing — including a malformed multipart upload. Also used for an unknown route or a wrong method.Fix the request; retrying as-is will not help.
unsupported_media400The file's real type is not one this endpoint accepts.Check the type against limits.upload in the catalog.
too_large413The upload is over the byte or pixel limit.Resize or re-encode before sending.
too_long400The clip is longer than the allowed duration.Trim it to within limits.videoMaxSeconds.
turnstile_failed403The bot challenge was not solved.Retry the challenge.
challenge_unavailable503The challenge provider could not be reached.Retry shortly; this fails closed on purpose.
bad_token401, 403The bearer token is missing or not valid (401), or valid but not allowed here (403).Create a new key or session.
token_expired401The token was valid but has expired.Create a new one.
credits_exhausted402This token has spent its frame budget.Wait for the reset, or use a key with a larger budget.
account_budget_exhausted429Your account has spent its frame allowance for the current window.Wait for the refill; Retry-After gives the seconds. This is the one limit you cannot work around with a new key or another machine.
ip_rate_limited429Your network has reached its hourly or daily budget.Honour Retry-After. This is the limit a client cannot opt out of.
global_rate_limited503The whole service is over its budget.Back off and retry; this protects every caller.
busy503No inference slot was free in time.Retry after a short delay.
ai_unavailable503The detection server is down, or the circuit breaker is open.Retry later; check aiStatus in the catalog first.
signin_unavailable503The sign-in service could not be reached, so the session could not be checked.Retry. This is not a rejection — do not clear the session on it.
demo_disabled503Inference has been switched off by an operator.Nothing to do client-side.
job_not_found404No such video job, or it belongs to another token.Job ids are scoped to the token that created them.
session_cooldown429A new token was requested too soon after the last one.Reuse the token you have; honour Retry-After.
store_unavailable503The service could not reach its own state store.Retry. Limits fail closed rather than opening up.
internal500An unexpected error.Retry once; report it with the X-Request-Id if it persists.

What to retry

Retry only 429 and 503, and only for as long as Retry-After says. Hammering a 429 is how a client gets blocked. A 4xx other than 429 means the request itself needs changing — retrying it unchanged will fail identically.

On this page