> ## Documentation Index
> Fetch the complete documentation index at: https://developers-staging.fmgsuite.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> How FMG Connect reports failures: the RFC 7807 problem body, the stable error codes, and which ones are safe to retry.

Every FMG Connect endpoint reports whole-request failures with a real HTTP
status code and an [RFC 7807](https://www.rfc-editor.org/rfc/rfc7807)
`application/problem+json` body — never a `200` in disguise.

```json theme={null}
{
  "type": "https://developers.fmgsuite.com/problems/forbidden",
  "title": "Forbidden.",
  "status": 403,
  "detail": "Token lacks scope mrc.messaging.write.",
  "instance": "/v1/mrc/messaging/messages",
  "code": "forbidden",
  "traceId": "1c95b936-ca30-4dfd-8627-e7e8b9280950",
  "retryable": false
}
```

## Fields

| Field | Meaning |
| - | - |
| `type` | URL of the page describing this error — `https://developers.fmgsuite.com/problems/{code}` |
| `title` | Short, fixed summary for the code |
| `status` | The HTTP status, repeated in the body |
| `detail` | Human-readable explanation specific to this occurrence |
| `instance` | The request path that failed |
| `code` | Stable machine-readable identifier — branch on this, not on `title` or `detail` |
| `traceId` | Correlation ID for this request; include it in any support request |
| `retryable` | Whether repeating the same request may succeed |
| `details` | Optional. Present on validation failures as an array of `{ path, message }` |

## Codes

| `code` | Status | Retry? | When |
| - | - | - | - |
| [`invalid_request`](/problems/invalid_request) | 400 | No | Malformed body or query; `details[]` lists each failing field |
| [`version_mismatch`](/problems/version_mismatch) | 400 | No | `X-API-Version` header disagrees with the `/v{N}` path prefix |
| [`unauthorized`](/problems/unauthorized) | 401 | After refreshing the token | Missing, malformed, or expired bearer token |
| [`forbidden`](/problems/forbidden) | 403 | No | Token is valid but lacks the scope the endpoint requires |
| [`not_found`](/problems/not_found) | 404 | No | No such route or resource |
| [`conflict`](/problems/conflict) | 409 | No | Request conflicts with the current state of the resource |
| [`payload_too_large`](/problems/payload_too_large) | 413 | No | Request body exceeds the size limit |
| [`unsupported_media_type`](/problems/unsupported_media_type) | 415 | No | Body is not `application/json` |
| [`rate_limited`](/problems/rate_limited) | 429 | Yes — honor `Retry-After` | Too many requests in the current window |
| [`downstream_unavailable`](/problems/downstream_unavailable) | 502 | Yes, with backoff | An FMG platform service behind Connect is unavailable or returned an invalid response |
| [`downstream_timeout`](/problems/downstream_timeout) | 504 | Yes, with backoff | An FMG platform service behind Connect did not respond in time |
| [`internal_error`](/problems/internal_error) | 500 | Yes, once with backoff | Unexpected failure inside FMG Connect |

## Retrying

Use `retryable` as the switch. When it is `true`, retry with exponential
backoff and jitter; on `429` wait at least the number of seconds in the
`Retry-After` header. When it is `false`, repeating the request unchanged
will fail the same way — fix the request, refresh credentials, or contact FMG.

Log the `traceId` for every failed request. It is the fastest way for FMG
support to find the request on our side.
