> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flows.super.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Codes

> Error response format, HTTP status codes, and the full catalog of machine-readable error codes.

All API errors follow a consistent JSON structure with a machine-readable `code` and a `request_id` for support.

```json theme={null}
{
  "error": {
    "message": "Human-readable error description",
    "code": "machine_readable_error_code",
    "details": {}
  },
  "request_id": "uuid-v4-request-identifier"
}
```

**Response headers:** `X-Request-ID` carries the same value as `request_id` for server-side log correlation.

**Fields:**

* `error.message` (string, required) — Human-readable error description
* `error.code` (string, optional) — Machine-readable error code for programmatic handling
* `error.details` (any, optional) — Additional context (e.g., validation errors)
* `request_id` (string, optional) — Unique request identifier for debugging

## HTTP status codes

| Status                      | Description                       | Usage                                                             |
| --------------------------- | --------------------------------- | ----------------------------------------------------------------- |
| `200 OK`                    | Successful request                | Most `GET`, `PATCH`, `DELETE` operations                          |
| `201 Created`               | Resource created                  | `POST` operations that create new resources                       |
| `400 Bad Request`           | Invalid request parameters        | Malformed DSL, invalid query parameters, bad execution references |
| `401 Unauthorized`          | Authentication required or failed | Missing/invalid bearer token, expired token, user not found       |
| `404 Not Found`             | Resource does not exist           | Flow or execution ID not found, entity not in database            |
| `409 Conflict`              | Resource already exists           | Duplicate flow name, duplicate execution ID, constraint violation |
| `422 Unprocessable Entity`  | Validation error                  | Request body fails validation, type errors, constraint violations |
| `500 Internal Server Error` | Unexpected server error           | Database errors, repository errors, unhandled exceptions          |

## Error code catalog

### `validation_error`

**HTTP 422.** Request body or parameters failed validation.

Review the `details` array, which lists each invalid field:

```json theme={null}
{
  "error": {
    "message": "Request validation failed",
    "code": "validation_error",
    "details": [
      {
        "type": "missing",
        "loc": ["body", "display_name"],
        "msg": "Field required",
        "input": {}
      }
    ]
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```

Each `details` item contains: `type` (error type), `loc` (JSON path to the field), `msg` (message), `input` (the invalid value), and optional `ctx` (constraints) and `url`.

### `invalid_dsl_input`

**HTTP 400.** The flow DSL definition is malformed or invalid — missing required fields, invalid task executor names, circular dependencies, or configurations that don't match executor schemas.

```json theme={null}
{
  "error": {
    "message": "Flow definition validation failed: tasks must be an array",
    "code": "invalid_dsl_input",
    "details": [
      "definition.tasks: Expected array but got object",
      "definition.version: Must be a positive integer"
    ]
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```

Ensure all tasks reference valid executors and that dependencies form a valid directed acyclic graph (DAG).

### `not_found`

**HTTP 404.** The requested resource does not exist — wrong ID, deleted resource, or a resource owned by a different organization (and therefore not visible).

```json theme={null}
{
  "error": {
    "message": "Flow not found with id: 550e8400-e29b-41d4-a716-446655440000",
    "code": "not_found"
  },
  "request_id": "660e8400-e29b-41d4-a716-446655440000"
}
```

### `conflict`

**HTTP 409.** The request conflicts with existing state or a database constraint — for example, a duplicate flow name within an organization. Use a different identifier, or retry with backoff for concurrent-modification conflicts.

### `bad_request`

**HTTP 400.** The request is syntactically correct but semantically invalid — invalid query parameter values, references to non-existent resources, or invalid state transitions.

```json theme={null}
{
  "error": {
    "message": "Can't find execution referenced in query parameter 'start_from_execution_id'",
    "code": "bad_request"
  },
  "request_id": "550e8400-e29b-41d4-a716-446655440000"
}
```

### `user_info_not_found`

**HTTP 401.** User information could not be retrieved from the authentication token — invalid/expired token or a deactivated account. Re-authenticate to obtain a fresh token.

### `repository_error`

**HTTP 500.** A database or repository-layer error occurred (connection failure, query timeout, deadlock). Retry with exponential backoff; contact support with the `request_id` if it persists.

### `service_error`

**HTTP 500** (or a custom status). An application service-layer error — business-logic failure, external integration failure, or unexpected state. Check the `message` for specifics.

### `internal_error`

**HTTP 500.** An unexpected internal error. These are automatically logged with full stack traces. Retry (it may be transient) and report the `request_id`.

### HTTP errors without a code

Some errors return a status code without an `error.code` field — for example `405 Method Not Allowed`, `415 Unsupported Media Type`, `413 Request Entity Too Large`, or `429 Too Many Requests`. Handle these by HTTP status.

## Handling errors

<Steps>
  <Step title="Check the HTTP status code first">
    ```python theme={null}
    if response.status_code >= 400:
        error = response.json().get("error", {})
        code, message = error.get("code"), error.get("message")
    ```
  </Step>

  <Step title="Branch on the error code">
    ```python theme={null}
    if code == "not_found":
        return None
    elif code == "validation_error":
        display_validation_errors(response.json()["error"]["details"])
    elif code == "user_info_not_found":
        redirect_to_login()
    ```
  </Step>

  <Step title="Retry transient server errors">
    ```python theme={null}
    RETRYABLE = {"repository_error", "service_error", "internal_error"}
    if code in RETRYABLE:
        retry_with_backoff(request)
    ```
  </Step>

  <Step title="Log the request_id for support">
    ```python theme={null}
    request_id = response.json().get("request_id") or response.headers.get("X-Request-ID")
    logger.error(f"API error: {message} (request_id: {request_id})")
    ```
  </Step>
</Steps>

## Summary

| Error code            | HTTP status | Category | Retryable                   |
| --------------------- | ----------- | -------- | --------------------------- |
| `validation_error`    | 422         | Client   | No — fix request            |
| `invalid_dsl_input`   | 400         | Client   | No — fix DSL                |
| `not_found`           | 404         | Client   | No — resource doesn't exist |
| `conflict`            | 409         | Client   | No — resource conflict      |
| `bad_request`         | 400         | Client   | No — fix request            |
| `user_info_not_found` | 401         | Auth     | No — re-authenticate        |
| `repository_error`    | 500         | Server   | Yes — retry                 |
| `service_error`       | 500         | Server   | Yes — retry                 |
| `internal_error`      | 500         | Server   | Yes — retry and report      |
| *(no code)*           | 4xx/5xx     | HTTP     | Depends on status           |
