Marble 2 beta

Errors and retries

Handle HTTP request failures separately from asynchronous operation failures.

  • A non-2xx HTTP response means the API request did not return a successful result. A timed-out submission can still be uncertain.
  • An accepted task can later finish with HTTP 200, done: true, and an error object inside the operation.

HTTP errors

StatusTypical meaningWhat to do
400Invalid argument or resource transitionCorrect the request before retrying
401Missing, unknown, expired, or revoked API keyReplace the credential
403Missing scope or project mismatchFix scopes or resource ownership
404Resource absent or task unavailable to this accountVerify the ID and beta access
409ID collision or idempotency key reused with a different bodyReuse the original body or choose a new logical ID
422JSON does not match the endpoint schemaCorrect field names, types, and required values
402Out of credits or a spend limit is reachedAdd credits or adjust the limit, then resubmit
429Submission or request rate exceededHonor Retry-After and reduce concurrency
500Unexpected server failureRetry safely; contact support if persistent
503Required capacity temporarily unavailableRetry with backoff and jitter

Validation errors can contain a structured detail array. Other failures often return a developer-readable detail string. Do not make program logic depend on the wording; branch on status, operation state, and structured error codes.

HTTP 503 responses may include Retry-After. Wait at least that long before retrying, and limit retries with backoff and jitter.

Machine-readable error codes

Rejected submissions put a stable string in the response's top-level code field. Failed operations use a numeric error.code from google.rpc.Code and put the more specific reason in a google.rpc.ErrorInfo entry inside error.details. Branch on the string code or reason, not the message.

FailureRead fromCode or reasonMeaning
Rate limitHTTP 429 response codeRATE_LIMIT_EXCEEDEDToo many requests were submitted in the current window. The request was not accepted; honor Retry-After.
Credits unavailableHTTP 402 response codeCREDITS_UNAVAILABLEThe account cannot start paid work because billing does not currently allow new usage. Add credits before retrying.
Spend limit exhaustedHTTP 402 response codeSPEND_LIMIT_EXCEEDEDAn account or project monthly spend limit was reached. Adjust the limit or wait for its reset before retrying.
Paid seat requiredHTTP 402 response codePAID_SEAT_REQUIREDA member on a Free seat submitted subscription work in an account whose seats are paid, after its signup credits were spent. An account admin can assign a seat. Developer API keys are not affected.
Content blockedOperation ErrorInfo.reason (error.code 3)CONTENT_POLICYThe model declined the request's content under its content policy. The operation is terminal and a retry will likely be declined again; change the prompt or images.
Task execution failedOperation ErrorInfo.reason (error.code 13)EXECUTION_FAILEDThe accepted task failed during execution. The operation is terminal; investigate before submitting a new task.
Task execution timeoutOperation ErrorInfo.reason (error.code 4)EXECUTION_TIMEOUTThe accepted task exceeded its execution deadline. The operation is terminal; a retry is a new task submission.

Numeric operation codes are intentionally broad. For example, code 4 (DEADLINE_EXCEEDED) can also accompany an expired task, so use the ErrorInfo.reason to distinguish the failure. See Rate limits and Billing for recovery guidance.

Operation failures

An accepted task may return a terminal operation such as:

json
{  "id": "op_example",  "done": true,  "error": {    "code": 13,    "message": "The task failed during execution.",    "details": [      {        "@type": "type.googleapis.com/google.rpc.ErrorInfo",        "reason": "EXECUTION_FAILED",        "domain": "api.worldlabs.ai"      }    ]  }}

Do not expect response on a failed terminal operation. For support, record the operation ID, task name, HTTP status from the original submission, and structured error metadata.

Retry without duplicate work

Create one Idempotency-Key before the first task submission. If the response is lost or a transient failure occurs, retry the same body with that same key. A successful replay returns the original operation.

Do not retry 400, 403, or 422 unchanged. For retryable reads and submissions, use capped exponential backoff with jitter. Respect Retry-After when present and stop after a bounded number of attempts or elapsed time.

Operation reads are safe to retry. Use a stable cancellation requestId when retrying :cancel.

Avoid retry storms

Limit retries globally per project, not only per worker. After an outage, drain queued submissions gradually. Persist operation IDs before acknowledging jobs to your own queue so a restarted worker resumes polling instead of submitting again.