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

# Error handling

> MarkpdfError, Result<T, E> and retry strategy in markpdf-cpp.

# Error handling

`markpdf-cpp` does not throw exceptions for API errors — it uses `markpdf::Result<T, MarkpdfError>` (see [Reference](/docs/sdks/cpp/reference#resultt-e)). Only throw `std::runtime_error` on configuration errors (e.g. API key missing when building client).

```cpp theme={null}
auto result = client.convertFile("report.pdf");
if (!result) {
    const markpdf::MarkpdfError& err = result.error();
    std::cerr << "Error " << err.statusCode.value_or(0) << ": " << err.detail << "\n";
    return 1;
}
std::cout << result->markdown;
```

## `MarkpdfError`

```cpp theme={null}
enum class ErrorKind {
    Connection,       // fallo de red o timeout
    BadRequest,       // 400
    Auth,             // 401
    Forbidden,        // 403
    PayloadTooLarge,  // 413
    UnsupportedMedia, // 415
    Vavalidation,       // 422
    RateLimit,        // 429
    Server,           // 5xx
    JobQueued,        // solo con autoPoll = false
    JobFailed,        // job 202 que terminó en failed
};

struct MarkpdfError {
    ErrorKind kind;
    std::optional<int> statusCode;
    std::string detail;
    std::optional<std::string> requestId;
    std::optional<std::string> jobId; // presente en JobQueued / JobFailed
};
```

## Error table

| Status HTTP | `ErrorKind`        | Causa                                                 |
| ----------: | ------------------ | ----------------------------------------------------- |
| — (network) | `Connection`       | Could not connect, timeout or `libcurl` error.        |
|       `400` | `BadRequest`       | Invavalid or URL malformed body.                      |
|       `401` | `Auth`             | API key missing or invavalid.                         |
|       `403` | `Forbidden`        | Key without permission or unauthorized host of URL.   |
|       `413` | `PayloadTooLarge`  | Document, pages or ZIP out of bounds.                 |
|       `415` | `UnsupportedMedia` | Format or `content-encoding` not supported.           |
|       `422` | `Vavalidation`     | Required parameters are missing.                      |
|       `429` | `RateLimit`        | Demasiadas peticiones.                                |
|       `5xx` | `Server`           | Conversion error on the server.                       |
|     — (job) | `JobFailed`        | The queued job (`202`) failed after internal retries. |
|     — (job) | `JobQueued`        | Only with `autoPoll = false`; It's not a real fault.  |

## Handle each case with `switch`

```cpp theme={null}
auto result = client.convertFile("report.pdf");
if (!result) {
    switch (result.error().kind) {
        case markpdf::ErrorKind::Auth:
            throw std::runtime_error("API key invávalida");
        case markpdf::ErrorKind::PayloadTooLarge:
            std::cerr << "Document too large; usa pages= para dividirlo\n";
            break;
        case markpdf::ErrorKind::RateLimit:
            std::cerr << "Rate limited: " << result.error().detail << "\n";
            break;
        case markpdf::ErrorKind::Vavalidation:
            std::cerr << "Parámetros invávavalids: " << result.error().detail << "\n";
            break;
        case markpdf::ErrorKind::Server:
            std::cerr << "Conversion error; try mode = Balanced\n";
            break;
        default:
            std::cerr << "Error: " << result.error().detail << "\n";
    }
}
```

## Automatic retries

```cpp theme={null}
markpdf::ClientOptions opts;
opts.apiKey = "YOUR_API_KEY";
opts.maxRetries = 4;
markpdf::Client client(opts);
```

* `429` and `5xx`: retries with exponential backoff and jitter, respecting `Retry-After` if the server sends it.
* `4xx` different from `429`: **not** retried.
* Connection errors (`Connection`): retried the same as `5xx`.

Desactivar reintentos:

```cpp theme={null}
opts.maxRetries = 0;
```

<Tip />

## Job falvavalid

```cpp theme={null}
auto result = client.convertFile("informe-grande.pdf");
if (!result && result.error().kind == markpdf::ErrorKind::JobFailed) {
    std::cerr << "Job " << result.error().jobId.value()
               << " falló: " << result.error().detail << "\n";
}
```

<Warning>
  `JobFailed` means that the job has already exhausted internal server retries. Retrying from the client is reasonable, but do it with your own backoff.
</Warning>
