Sociaro

Errors

Every status you can receive, what it means, and what to do.

status meaning what to do
400 The request was not understood — an unknown parameter, a value outside what the model accepts, or something you sent that we could not use, such as a reference image we could not download. Read the message; it names the field or the item. Retrying the same request unchanged will not help.
401 The key is missing, wrong, or revoked. Check the Authorization header. Keys start with sk-.
403 The key exists but may not reach this model. GET /v1/models shows what it may reach.
404 No such job, or no such door. Check the id and the path. A job id belongs to the key that made it.
409 Your account is in a state that has to change before the call can work. Today that means one thing: your organisation has no spending limit configured, so there is no remainder to report. Retrying will not help and nothing is wrong with your request — contact your account manager.
429 Out of balance, or too many requests. The message says which — for OUR refusals, which is what a 429 on a submit almost always is. For balance, top up in the console. The exception is a 429 the GENERATOR gave us on /v1/spicy/*: that one is about our account with it, so you get the neutral message and nothing to read — retry it, and tell us if it persists.
500 Something broke on our side. Retry. If it persists, tell us — it is ours to fix, not yours.
502 A vendor failed or could not be reached — except on GET /v1/balance, where no vendor is involved and a 502 means our own key check failed. On a poll, retry — and if one vendor is down, another model often is not. On a submit, do not retry blindly: there is no idempotency key on these routes, so a 502 can equally mean the generator accepted your job and started charging for it while its id never reached us. Check whether a job appeared before sending the same request again. The same caution applies to a 503 on a submit.
503 Temporarily unavailable — usually a shared, rate-limited resource that is busy. Read the message. A refusal raised before anything was submitted says so, and is safe to retry as-is — reference-image preparation is the common one. Otherwise treat it like a 502 on a submit: check whether a job appeared first.
504 The vendor took too long. For media, use the async door — it is built for slow work.

Reading a refusal

Errors carry a message written to be read:

{"error": {"message": "budget exceeded for this organisation: its spend has reached the balance it was topped up to. Top up in the console to continue."}}

One exception, and it is the generator's doing. When a generator refuses a submission on the uncensored line — a bad parameter, an image it will not read — its own body is forwarded to you whole, in ITS shape rather than the envelope above, because its wording names the field and the limit and ours would only paraphrase. Names of the services and hosts behind the model are substituted out of it. So parse defensively on those routes: read error.message when it is there, and fall back to the HTTP status when the body is shaped some other way.

One class of refusal is NOT forwarded on that line, and it is the one that would tell you nothing useful: when the generator turns us away over OUR OWN account with it — a 401, 403, 407 or 429 — you get its HTTP status (so you can still tell retryable from terminal, and a 429 is retryable) and our neutral {"error": {"message": … }} instead of its body, because that sentence is about our arrangement with the generator and not about your request. Those are ours to fix, and they are logged on our side.

That substitution is specific to the uncensored line. The other two doors answer differently, and a client that applies the same parsing to them will be wrong: /v1/byteplus/* passes the generator's envelope through UNCHANGED, names included, and its error.code is the generator's vocabulary rather than ours; /v1/images/async reports a failure through its webhook as { job_id, status, model } with no error object at all.

We keep them plain on purpose. An error that says only "Bad Gateway" when the real cause is an empty balance costs an hour of looking for an outage that never happened — that has happened here, which is why these messages say what they mean.

What never happens silently

  • A refused request is never charged.
  • A failed generation is never charged, and still appears in your Logs.
  • A job that cannot be priced is withheld, not delivered free — so a missing charge is never the first sign that something went wrong.