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

# Error Handling

> Handle API errors gracefully with the Law4Devs Java SDK.

## Exception Hierarchy

All SDK exceptions extend `eu.law4devs.sdk.exceptions.Law4DevsException`, which itself extends `RuntimeException`.

```
RuntimeException
└── Law4DevsException          base — any SDK error
    ├── NotFoundError          404 — resource not found
    ├── ValidationError        400 — invalid parameters
    ├── RateLimitError         429 — rate limit exceeded
    └── ServerError            5xx — server-side error
```

Every exception exposes a `getStatusCode()` method:

```java theme={null}
try {
    Article article = client.articles().get("gdpr", 9999);
} catch (NotFoundError e) {
    System.out.println("Not found: " + e.getMessage());  // message from API
    System.out.println("Status: " + e.getStatusCode());  // 404
}
```

***

## Catching Specific Errors

```java theme={null}
import eu.law4devs.sdk.exceptions.Law4DevsException;
import eu.law4devs.sdk.exceptions.NotFoundError;
import eu.law4devs.sdk.exceptions.RateLimitError;
import eu.law4devs.sdk.exceptions.ValidationError;

try {
    var page = client.articles().list("invalid-framework");
} catch (NotFoundError e) {
    // Framework not found
    System.out.println("Framework not found: " + e.getMessage());
} catch (ValidationError e) {
    // Bad request parameters
    System.out.println("Invalid request: " + e.getMessage());
} catch (RateLimitError e) {
    // Retry after a delay (SDK already retried 3 times)
    System.out.println("Rate limit hit: " + e.getMessage());
} catch (Law4DevsException e) {
    // All other SDK errors (server errors, network failures)
    System.out.println("SDK error (" + e.getStatusCode() + "): " + e.getMessage());
}
```

***

## Automatic Retry

The SDK automatically retries on `429 Too Many Requests` and `5xx Server Error` responses using exponential backoff:

| Attempt   | Wait      |
| --------- | --------- |
| 1st retry | 1 second  |
| 2nd retry | 2 seconds |
| 3rd retry | 4 seconds |

After `maxRetries` (default `3`) attempts, the exception is re-thrown.

To disable retries, set `maxRetries(0)`:

```java theme={null}
Law4DevsClient client = Law4DevsClient.builder()
    .apiKey(System.getenv("LAW4DEVS_API_KEY"))
    .maxRetries(0)
    .build();
```

<Note>
  `NotFoundError` (404) and `ValidationError` (400) are never retried — they represent client errors that will not resolve by retrying.
</Note>

***

## Network Errors

Connection failures (timeout, DNS, SSL) throw `Law4DevsException` with a message describing the failure:

```java theme={null}
import eu.law4devs.sdk.exceptions.Law4DevsException;

try {
    var page = client.frameworks().list();
} catch (Law4DevsException e) {
    System.out.println("SDK error: " + e.getMessage());
}
```

***

## Errors in `iter()` Loops

Exceptions can be thrown mid-iteration if a page request fails. Wrap `iter()` loops in a try/catch:

```java theme={null}
try {
    for (ArticleSummary a : client.articles().iter("gdpr")) {
        System.out.println(a.title());
    }
} catch (Law4DevsException e) {
    System.out.println("Error mid-iteration: " + e.getMessage());
}
```

***

## Best Practices

* Always catch `Law4DevsException` as a fallback to handle unexpected errors
* Wrap `iter()` loops in a try/catch — exceptions can occur mid-iteration if a page request fails
* Use `getStatusCode()` to distinguish error types when handling `Law4DevsException` generically
* For batch processing, implement a retry strategy at the application level if you need finer control than the built-in retry
* Prefer specific exception types (`NotFoundError`, `RateLimitError`) over the base class for cleaner error handling
