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

# Errors

> Error envelopes, HTTP status codes, the full error-code list, and how to recover.

ClawLink distinguishes between an action that **couldn't start** (`blocked` — you can
usually fix it and retry) and one that **ran and failed** (`failed`). Both are reported in
a normalized shape so you can branch programmatically.

## Error envelopes

Which envelope you get depends on the endpoint.

### Canonical endpoints

`POST /api/executions`, `GET /api/executions/{id}`, and the discovery endpoints return an
execution summary. On a problem, `status` is `"blocked"` or `"failed"`:

```json theme={null}
{
  "execution_id": null,
  "status": "blocked",
  "integration_id": "gmail",
  "action_id": "send_email",
  "display": { "title": "Execution blocked", "summary": "Gmail isn't connected yet." },
  "error_code": "integration_not_connected",
  "message": "Gmail isn't connected yet.",
  "recommended_next_action": {
    "tool": "clawlink.connect_app",
    "input": { "integration_id": "gmail" }
  }
}
```

* `blocked` → the action never ran (policy, missing/expired connection, ambiguous
  connection). `execution_id` is `null`. Fix the cause and retry.
* `failed` → the action ran and errored. `execution_id` is set.
* `recommended_next_action` appears when the fix is to connect or re-auth an app.

### Tool endpoint

`POST /api/tools/{tool_name}/execute` returns the raw payload with `ok: false` and a
structured `error`, plus a `canonical` block mirroring the shape above:

```json theme={null}
{
  "ok": false,
  "toolName": "gmail_send_email",
  "integration": "gmail",
  "error": {
    "type": "validation",
    "code": "invalid_arguments",
    "message": "Missing required field: subject",
    "retryable": false
  },
  "canonical": { "status": "failed", "error_code": "validation_error", "message": "Missing required field: subject" }
}
```

`error.retryable` tells you whether retrying the same request could succeed (e.g. a
transient `rate_limit` or `network` error).

### Simple guard errors

Malformed requests and auth failures (before any execution) return a bare object:

```json theme={null}
{ "error": "integration_id, action_id, and object input are required" }
```

## HTTP status codes

<Tabs>
  <Tab title="/api/executions">
    | Status | Meaning                                                         |
    | ------ | --------------------------------------------------------------- |
    | `200`  | `status: "succeeded"`                                           |
    | `400`  | Missing `integration_id`, `action_id`, or object `input`        |
    | `401`  | Missing/invalid API key                                         |
    | `409`  | `status: "blocked"` (e.g. confirmation required, not connected) |
    | `500`  | `status: "failed"`, or an unexpected server error               |
  </Tab>

  <Tab title="/api/tools/.../execute">
    | Status | Meaning                                                       |
    | ------ | ------------------------------------------------------------- |
    | `200`  | Succeeded (`ok: true`)                                        |
    | `400`  | Validation error                                              |
    | `401`  | Auth failure / re-auth required                               |
    | `402`  | Billing required (trial expired, payment failed, usage limit) |
    | `403`  | Missing OAuth scopes                                          |
    | `404`  | Tool not found                                                |
    | `409`  | Needs connection / ambiguous connection                       |
    | `412`  | Confirmation required (set `confirmed: true`)                 |
    | `413`  | File upload exceeds the size cap                              |
    | `422`  | Configuration error                                           |
    | `429`  | Rate limited (honor `Retry-After`)                            |
    | `503`  | Provider unavailable                                          |
    | `500`  | Unexpected error                                              |
  </Tab>
</Tabs>

## Error codes

`error_code` (canonical) values and how to recover:

| `error_code`                | Meaning                                              | What to do                                                           |
| --------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------- |
| `unauthorized`              | Invalid API key, or provider auth rejected           | Check the key; the app may need re-auth                              |
| `forbidden`                 | Connected account lacks the required scopes          | Reconnect with the needed permissions                                |
| `integration_not_found`     | Unknown `integration_id`                             | Check the slug via `/api/integrations`                               |
| `action_not_found`          | Unknown `action_id` for that integration             | Check via `/api/actions?integration_id=…`                            |
| `integration_not_connected` | App isn't connected                                  | Connect it in the dashboard (`recommended_next_action`)              |
| `reauth_required`           | Connection expired or revoked                        | Reconnect the app (`recommended_next_action` with `force_reconnect`) |
| `validation_error`          | Bad or missing arguments                             | Fix `input`; check the action's `input_schema`                       |
| `policy_blocked`            | Write needs confirmation, or an ambiguous connection | Resend with `confirm: true`, or disambiguate the connection          |
| `rate_limited`              | Provider rate limit hit                              | Back off and retry; honor `Retry-After`                              |
| `timeout`                   | Provider took too long                               | Retry                                                                |
| `unsupported_operation`     | Provider/operation unavailable                       | Don't retry as-is                                                    |
| `execution_failed`          | Action ran and failed                                | Inspect `message` / `hint`                                           |

<Tip>
  When present, the `hint` field contains concrete recovery guidance — for example, the
  upload-and-retry `curl` for a missing local file (see [File uploads](/api/file-uploads)).
  Surface it; it's written to be actionable.
</Tip>

## Recovering connection problems

`integration_not_connected` and `reauth_required` come with a
`recommended_next_action` pointing at the connect flow:

```json theme={null}
{
  "recommended_next_action": {
    "tool": "clawlink.connect_app",
    "input": { "integration_id": "gmail", "force_reconnect": true }
  }
}
```

Connecting and re-authing apps is a hosted, browser-based flow done from the
[dashboard](https://claw-link.dev) (**Connections**). Once the app is healthy, retry the
original request unchanged.
