---
url: /orchestration/guide/errors-and-retries.md
---

> Documentation index: https://developer.civitai.com/llms.txt — every page on this site has a markdown version at its URL + `.md`.

# Errors & Retries

Errors surface in two places:

1. **HTTP responses** on the submit / get / update endpoints — validation, auth, rate-limit, or server issues.
2. **Step status** inside a returned workflow — the request succeeded, but a step reached `failed`, `expired`, or `canceled`.

The orchestrator races providers, so a transient provider failure (a worker crashing, a slow region) is usually invisible: another provider claims the job. You see a step-level failure only once every viable provider is exhausted.

## HTTP error shape

Error responses use the standard [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807) `application/problem+json` shape ([`ProblemDetails`](https://developer.civitai.com/orchestration/reference/operations/SubmitWorkflow.md) / [`ValidationProblemDetails`](https://developer.civitai.com/orchestration/reference/operations/SubmitWorkflow.md)):

```json
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errors": {
    "steps[0].input.resolution": [
      "The value '4k' is not valid for resolution."
    ]
  }
}
```

* `status` — the HTTP status code (also in the response line).
* `title` — short, human-readable summary.
* `detail` — longer description when the orchestrator can give one.
* `errors` — present on `400` validation failures; JSON Pointer–style paths → list of messages.
* `instance` / `type` — optional URIs identifying the specific occurrence and error class.

## HTTP status taxonomy

| Code | Meaning | Retry? |
|------|---------|--------|
| `400 Bad Request` | Body failed validation. `errors` map tells you exactly which fields. | **No** — fix the request. |
| `401 Unauthorized` | Missing / expired / malformed bearer token. | **No** — obtain a new token. |
| `403 Forbidden` | Token is valid but can't perform this operation (recipe not enabled for your tier, mature content not permitted, etc.). | **No** — request access; don't retry as-is. |
| `404 Not Found` | Workflow or blob ID doesn't exist (or the token can't see it). | **No** — check the ID. |
| `409 Conflict` | The workflow is in a state that blocks this mutation (e.g. updating a step that already started). | **Maybe** — refetch and reconcile. |
| `429 Too Many Requests` | Rate-limit hit. | **Yes, with backoff.** |
| `5xx Server Error` | Transient orchestrator issue. | **Yes, with backoff.** |

For `429` / `5xx`: exponential backoff with jitter, capped at ~30 s between attempts, giving up after ~5 tries.

## Step-level failures

A `200` / `202` on submit means the workflow was accepted; steps can still fail later. The [`Workflow`](https://developer.civitai.com/orchestration/reference/operations/GetWorkflow.md) you get back (or by webhook) carries per-step status:

```json
{
  "id": "wf_01HXYZ...",
  "status": "failed",
  "steps": [
    {
      "name": "0",
      "$type": "videoGen",
      "status": "failed",
      "jobs": [
        {
          "status": "failed",
          "reason": "no_provider_available",
          "blockedReason": null
        }
      ]
    }
  ]
}
```

Workflows, steps and jobs share one status enum ([Status lifecycle](https://developer.civitai.com/orchestration/guide/workflows.md#status-lifecycle)); its terminal states [never change](https://developer.civitai.com/orchestration/guide/results-and-webhooks.md#delivery-semantics).

The `reason` and `blockedReason` fields on failed jobs are the best hint at *why*:

| `reason` | What it means | Your move |
|----------|---------------|-----------|
| `no_provider_available` | No provider can run this job with the given inputs (unusual resolution, unsupported duration, restricted region, etc.). | Relax inputs, try another `provider`/`version`, or retry later. |
| `blocked` | The job was blocked by content moderation. `blockedReason` explains further. | Don't retry the same input; rework the prompt or image. |
| `timeout` / `expired` | Job exceeded its internal deadline. | Safe to resubmit — possibly with a smaller workload. |
| `canceled` | The workflow was canceled, usually via [`DeleteWorkflow`](https://developer.civitai.com/orchestration/reference/operations/DeleteWorkflow.md); see [Step `canceled` unexpectedly](#common-gotchas) for the other causes. | No retry unless you actually want to re-run it. |

When `reason` is absent, the failure is generic — safe to retry once with the same body.

## Webhook retries

The orchestrator retries transient failures on your callback endpoint automatically; see [Delivery semantics](https://developer.civitai.com/orchestration/guide/results-and-webhooks.md#delivery-semantics) for the ordering guarantees.

## Common gotchas

* **Blob URL stopped working.** Check its `urlExpiresAt`: past it a signed URL is rejected, which isn't a failure. Get a fresh one as described in [Blobs in results](https://developer.civitai.com/orchestration/guide/results-and-webhooks.md#blobs-in-results). For a public-tier URL it means the object was deleted; refetching won't bring it back, so regenerate it.
* **`202` after `wait=90`.** The workflow didn't finish within those 90 s (keep `wait` below [your HTTP client's timeout](https://developer.civitai.com/orchestration/guide/getting-started.md#_3-poll-if-you-didn-t-wait-inline)); continue via webhooks or polling.
* **Step `canceled` unexpectedly.** Check whether another process called [`DeleteWorkflow`](https://developer.civitai.com/orchestration/reference/operations/DeleteWorkflow.md). The orchestrator also cancels on its own when a per-recipe endpoint's caller disconnects, when a step it depends on failed, or when your Buzz runs out (before the work is scheduled, or mid-run for a runtime-billed custom Comfy step).
