<!-- https://cutedyno.com/docs/errors -->

# Error reference

Every error code the API returns, what causes it, and whether retrying helps.

Every failure from `/v1` and `/mcp` uses one envelope. Branch on `code`; it is stable. Never branch on `message`, which is written for humans and will change.

```json
{
  "error": {
    "code": "accounts_not_found",
    "message": "None of the supplied accountIds matched a connected account in this profile.",
    "docsUrl": "https://cutedyno.com/docs/errors#accounts_not_found",
    "requestId": "8f14e45f-ea0c-4d7a-9f1a-2b3c4d5e6f70"
  },
  "message": "None of the supplied accountIds matched a connected account in this profile."
}
```

Four fields carry the useful information:

- **`code`** — the stable identifier to switch on.
- **`message`** — a human explanation, safe to log and usually safe to show an operator.
- **`docsUrl`** — a deep link to this page, anchored at the code.
- **`requestId`** — echoes the `X-Request-Id` header. Quote it when reporting a problem and we can find the exact request.

Some codes add a `details` object. `plan_limit` carries `entitlement`, `usage`, and `limit`; `insufficient_permission` carries the `required` permission; `daily_post_limit` carries `limit`, `used`, and `resetsAt`.

## Handling errors in code

```typescript
import { CuteDynoError } from '@cutedyno/node';

try {
  await cutedyno.posts.create(input);
} catch (error) {
  if (!(error instanceof CuteDynoError)) throw error;

  switch (error.code) {
    case 'no_accounts_connected':
    case 'accounts_not_found':
      return promptUserToReconnect();

    case 'plan_limit':
    case 'trial_expired':
      return showUpgradePrompt(error.details);

    case 'rate_limit_exceeded':
      return retryAfter(error.retryAfter ?? 60);

    default:
      if (error.isRetryable) return scheduleRetry();
      log.error('CuteDyno rejected the post', {
        code: error.code,
        requestId: error.requestId,
      });
      throw error;
  }
}
```

The rule of thumb: **`4xx` is your bug or your user's state, `5xx` and `429` are ours.** Retry the second group with the same [idempotency key](/docs/guides/idempotency); fix or surface the first.

## Codes by status

{{error-codes}}

## Legacy error format

Before this envelope existed, errors were `{ "error": "some string" }`. If you have a client written against that shape and cannot change it yet, send:

```text
CuteDyno-Error-Format: legacy
```

and responses revert to `{ "error": "<message>", "code": "<code>" }`. This is a migration aid with a limited life. Prefer reading `error.code` from the structured shape, which every current response already includes.

## MCP errors

Tool calls surface the same codes. A failing tool returns `isError: true` with the code, message, and request ID in the text, so an agent can explain what went wrong rather than retrying blindly. See [MCP](/docs/mcp).
