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

# Errors

> Every error code, and what to do about it.

Switch on `code`. It is stable, and `message` may be reworded.

```json theme={null}
{
  "error": { "code": "not_found", "message": "no such person" },
  "request_id": "01J9K..."
}
```

Quote the `request_id` when you report a problem. It identifies the request in our logs.

## Codes

| Code | HTTP | What it means |
| - | - | - |
| `invalid_input` | 400 | A parameter or body field is wrong |
| `bad_request` | 400 | A required field is missing |
| `unauthorized` | 401 | No token, or an unknown one |
| `workspace_required` | 401 | A Clerk token without a workspace |
| `feature_not_in_plan` | 402 | This plan lacks `api_keys` or `mcp` |
| `limit_exceeded` | 402 | A usage cap was reached |
| `forbidden` | 403 | Valid credential, missing scope |
| `not_found` | 404 | No such record, or no such route |
| `conflict` | 409 | An idempotency key was reused |
| `endpoint_unreachable` | 422 | Your webhook endpoint did not answer |
| `rate_limited` | 429 | Too many requests on this credential |
| `internal_error` | 500 | A bug on our side |
| `bad_gateway` | 502 | The authorization server did not answer |

## What to do

> [accordion] 400 invalid\_input and bad\_request
>
> Fix the one field named in `details.field`. Unknown parameters come back as
> `details.unknown_parameters`.
>
> A filter typo shows up here instead of as a wrong list.

> [accordion] 401 unauthorized and workspace\_required
>
> Check the `Authorization: Bearer ...` header. A revoked key is replaced in Settings, not
> recovered. The response carries `WWW-Authenticate`.
>
> `workspace_required` means a valid Clerk token with no organization, or an organization
> with no Ziplined workspace. Pick a workspace and connect again. It is never guessed for
> you.

> [accordion] 402 feature\_not\_in\_plan and limit\_exceeded
>
> Show the `upgrade_url` from `details`. Retrying will not help.
>
> `limit_exceeded` means a usage cap on the plan was reached. Upgrade, or ask for less.

> [accordion] 403 forbidden and 404 not\_found
>
> Issue a key with the scope the endpoint needs.
>
> A resource in another workspace answers `not_found`, not `forbidden`. A missing record
> and a foreign record are deliberately one answer, so the error is not a proof of
> existence.

> [accordion] 409 conflict
>
> Use a fresh `Idempotency-Key` for a new request.
>
> If the first request is still in flight, wait and read the result. Do not retry.

> [accordion] 422 endpoint\_unreachable
>
> Only on `POST /v1/integrations`. Your endpoint gave no 2xx within ten seconds to the
> signed `ping`, and no destination was created.
>
> Make the endpoint answer 2xx to a POST it does not recognise, then create it again.

> [accordion] 429 rate\_limited
>
> Back off for `Retry-After` seconds.
>
> `RateLimit-Remaining` on every response lets you avoid this.

> [accordion] 500 internal\_error and 502 bad\_gateway
>
> Retry once. If `internal_error` persists, report the `request_id`.
>
> `bad_gateway` happens only on the OAuth discovery paths. Nothing in your request caused
> it.

## Errors from MCP tools

An error inside a tool is a tool error, not a transport error. The result has
`isError: true` and `structuredContent` carries the same `code` and `message`.

`rate_limited` adds `retry_after` in seconds. Only missing or invalid authentication is an
HTTP status, because the client answers it with an OAuth handshake.

## Errors on a run

A failed background run carries its own `error` and `error_code`, separate from the codes
above.

| Code | What it means |
| - | - |
| `handler_threw` | The job raised an exception |
| `nothing_written` | The job produced no rows |

`nothing_written` is a result, not a crash. The detail behind `handler_threw` stays in our
logs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.