Error codes

When a job fails, its error_code carries a machine-readable reason and result carries a short message. These are the codes the fulfillment pipeline assigns (from curl errno, HTTP status, and response body).

Code reference

CodeRetryableMeaningHow to resolve
authyes (critical)Provider rejected the credentials (HTTP 401 / 403). Bad or missing API key / endpoint.Fix the provider key or endpoint in lib/faucet_config.php. The operator is emailed; the job retries automatically once the key is valid.
out_of_creditsyes (critical)Provider balance exhausted (HTTP 402, or a body mentioning "insufficient" / "credit" / "balance", e.g. RunPod balance fail, OpenAI/Azure 429 insufficient_quota, Anthropic "credit balance too low").Top up the provider balance. The operator is emailed; the job retries automatically once funded.
rate_limityesProvider throttled the request (HTTP 429, not a quota/credit issue).Nothing needed - the tiered backoff waits it out. Reduce concurrency if it persists.
timeoutyesThe call timed out, or the job sat in running past its per-mode wall-clock limit and was reaped (text 300 s, image 900 s, video 2400 s).Transient. It re-queues and retries. Persistent timeouts point at a wedged provider or too-large a request.
networkyesCould not connect / resolve the provider host (DNS or connection failure).Check the endpoint host and that the provider is reachable from the worker.
transportyesA lower-level curl transport error not classified as timeout or network.Usually transient; retries. Inspect the result message if it repeats.
provider_erroryesProvider returned a 5xx, or reported the job FAILED / CANCELLED, or returned no usable job id.Provider-side fault. Retries automatically; check the provider's status if it persists.
empty_responseyesThe call succeeded but returned no content (empty inference text, or a COMPLETED provider job with no output).Retries. If it keeps happening, the prompt or model config is producing empty output.
bad_requestnoThe request is malformed for the provider (e.g. no media provider configured for the mode, empty prompt, or a model routed to the wrong path).Fix the request or configuration. This is the only non-retryable code - the job fails permanently.
erroryesGeneric uncaught failure (a thrown exception not carrying a specific code, e.g. a failed media adopt / unwritable file).Read the result message. Transient issues retry; a code bug needs a fix.
http_<code>yesAn HTTP status the classifier did not map to a specific code (e.g. http_404, http_400 from a provider).Inspect the message. Often an endpoint / path / payload mismatch.

Retry behavior

Every code except bad_request is retryable. A retryable job with retries remaining is re-queued with tiered backoff by remaining retries:

Retries leftBackoff before next attempt
32 minutes
210 minutes
11 hour

When retries are exhausted, the job is marked permanently failed with its last error_code. On the retry path the worker clears external_job_id so an async media job is resubmitted fresh.

Critical codes and alerting

auth and out_of_credits are critical: they email the operator (rate-limited to once per code per 30 minutes) and are always appended to an alert log. Every failure - critical or not - is also mirrored to the fleet error_reports bar. Because balance exhaustion is a real-money event on shared paid keys, a proactive balance poller (planned) warns before jobs start failing.

Failed-job shape

{
  "id": 5140,
  "mode": "image",
  "model": "gpt-image-2",
  "status": "failed",
  "error_code": "out_of_credits",
  "result": "Azure gpt-image failed: HTTP 429: insufficient_quota ...",
  "retries_left": 0,
  "completed_at": "2026-07-12T18:10:00Z"
}

While a job is still retrying it returns to status: queued with the error_code and a next_retry_time set, rather than failed.