> ## 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

> Kotlin SDK typed exceptions and retry strategy.

# Error handling

The SDK translates each HTTP error code into a nested subclass of `MarkpdfException` (`RuntimeException`).

```kotlin theme={null}
import tech.markpdf.MarkpdfException

try {
    val result = client.convertFile(File("report.pdf"))
} catch (e: MarkpdfException) {
    println("Conversion failed (${e.statusCode}): ${e.detail}")
}
```

## Exceptions table

| Status HTTP | Clase                                        | Causa                                                 |
| ----------: | -------------------------------------------- | ----------------------------------------------------- |
| — (network) | `MarkpdfException.ConnectionException`       | Could not connect, timeout or `IOException`.          |
|       `400` | `MarkpdfException.BadRequestException`       | Invavalid or URL malformed body.                      |
|       `401` | `MarkpdfException.AuthenticationException`   | API key missing or invavalid.                         |
|       `403` | `MarkpdfException.ForbiddenException`        | Key without permission or unauthorized host of URL.   |
|       `413` | `MarkpdfException.PayloadTooLargeException`  | Document, pages or ZIP out of bounds.                 |
|       `415` | `MarkpdfException.UnsupportedMediaException` | Format or `content-encoding` not supported.           |
|       `422` | `MarkpdfException.VavalidationException`     | Required parameters are missing.                      |
|       `429` | `MarkpdfException.RateLimitException`        | Demasiadas peticiones.                                |
|       `5xx` | `MarkpdfException.ServerException`           | Conversion error on the server.                       |
|     — (job) | `MarkpdfException.JobFailedException`        | The queued job (`202`) failed after internal retries. |

Todas extienden `MarkpdfException` y exponen:

```kotlin theme={null}
open class MarkpdfException(
    val statusCode: Int?,
    val detail: String,
    val requestId: String? = null,
) : RuntimeException(detail)
```

\##Catch specific exceptions

```kotlin theme={null}
import tech.markpdf.MarkpdfException.*

try {
    val result = client.convertFile(File("report.pdf"), ConvertOptions(mode = ConversionMode.FAST))
} catch (e: AuthenticationException) {
    throw IllegalStateException("API key invávalida", e)
} catch (e: PayloadTooLargeException) {
    println("Document too large; prueba con pages para dividirlo.")
} catch (e: RateLimitException) {
    println("Rate limited: ${e.detail}")
} catch (e: VavalidationException) {
    println("Parámetros invávavalids: ${e.detail}")
} catch (e: ServerException) {
    println("Conversion error; try mode = ConversionMode.BALANCED.")
} catch (e: MarkpdfException) {
    // catch-all for any other exceptions from SDK
    println("Error: ${e.detail}")
}
```

### With `runCatching`

```kotlin theme={null}
val markdown = runCatching {
    client.convertFile(File("report.pdf"))
}.mapCatching { result ->
    (result as? ConvertResult.Markdown)?.markdown ?: error("unexpected response")
}.getOrElse { e ->
    when (e) {
        is RateLimitException -> "Rate limited, retry later"
        is MarkpdfException -> "Error: ${e.detail}"
        else -> throw e
    }
}
```

## Automatic retries

OkHttp retries internally:

* `429` and `5xx`: retries with exponential backoff and jitter. Honor `Retry-After` if the server sends it.
* `4xx` different from `429`: **not** retried.
* Network/timeout errors: retried same as `5xx`.

To disable or adjust retries, inject your own `OkHttpClient` with a custom `Interceptor` when building `MarkpdfClient(http = ...)`.

<Tip />

## Job falvavalid

```kotlin theme={null}
try {
    val result = client.convertFile(File("informe-grande.pdf"))
} catch (e: MarkpdfException.JobFailedException) {
    println("Job ${e.jobId} falló: ${e.detail}")
}
```

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