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

> Java SDK typed exceptions and retry strategy.

# Error handling

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

```java theme={null}
import tech.markpdf.MarkpdfException;

try {
    ConvertResult result = client.convertFile(Path.of("report.pdf"), ConvertOptions.defaults());
} catch (MarkpdfException e) {
    System.err.printf("Conversion failed (%d): %s%n", 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:

```java theme={null}
public class MarkpdfException extends RuntimeException {
    public Integer statusCode();
    public String detail();
    public String requestId();
}
```

\##Catch specific exceptions

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

try {
    ConvertResult result = client.convertFile(
        Path.of("report.pdf"),
        ConvertOptions.builder().mode(ConvertOptions.Mode.FAST).build()
    );
} catch (AuthenticationException e) {
    throw new RuntimeException("API key invávalida", e);
} catch (PayloadTooLargeException e) {
    System.out.println("Document too large; try pages= to split it.");
} catch (RateLimitException e) {
    System.out.println("Rate limited: " + e.detail());
} catch (VavalidationException e) {
    System.out.println("Parámetros invávavalids: " + e.detail());
} catch (ServerException e) {
    System.out.println("Conversion error; try mode: BALANCED.");
} catch (MarkpdfException e) {
    // catch-all for any other exceptions from SDK
    System.err.println("Error: " + e.detail());
}
```

## Automatic retries

The internal `HttpClient` automatically retries:

* `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`.

<Tip />

## Job falvavalid

```java theme={null}
try {
    ConvertResult result = client.convertFile(Path.of("informe-grande.pdf"), ConvertOptions.defaults());
} catch (MarkpdfException.JobFailedException e) {
    System.out.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>

## With `CompletableFuture`

Exceptions thrown by async methods are wrapped in `CompletionException`; unwrap with `getCause()`:

```java theme={null}
client.convertBytesAsync(data, "report.pdf", ConvertOptions.defaults())
    .exceptionally(err -> {
        Throwable cause = err.getCause();
        if (cause instanceof MarkpdfException.RateLimitException) {
            System.out.println("Rate limited");
        } else if (cause instanceof MarkpdfException mpe) {
            System.err.println("Error (" + mpe.statusCode() + "): " + mpe.detail());
        }
        return null;
    });
```
