> ## 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 PHP SDK.

## Exception Hierarchy

All SDK exceptions extend `Law4Devs\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 `statusCode` property:

```php theme={null}
try {
    $article = $client->articles->get('gdpr', 9999);
} catch (\Law4Devs\Exceptions\NotFoundError $e) {
    echo 'Not found: ' . $e->getMessage() . "\n";  // message from API
    echo 'Status: ' . $e->statusCode . "\n";        // 404
}
```

***

## Catching Specific Errors

```php theme={null}
use Law4Devs\Exceptions\Law4DevsException;
use Law4Devs\Exceptions\NotFoundError;
use Law4Devs\Exceptions\RateLimitError;
use Law4Devs\Exceptions\ValidationError;

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

***

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

```php theme={null}
$client = new \Law4Devs\Client(
    apiKey:     getenv('LAW4DEVS_API_KEY'),
    maxRetries: 0,
);
```

***

## Network Errors

Connection failures (timeout, DNS, SSL) throw `Law4DevsException` with `statusCode` of `null`:

```php theme={null}
use Law4Devs\Exceptions\Law4DevsException;

try {
    $page = $client->frameworks->list();
} catch (Law4DevsException $e) {
    if ($e->statusCode === null) {
        echo 'Network error: ' . $e->getMessage() . "\n";
    }
}
```

***

## Best Practices

* Always catch `Law4DevsException` as a fallback to handle unexpected errors
* Check `$e->statusCode` to distinguish network errors (`null`) from API errors
* Wrap `iter()` loops in a try/catch — exceptions can occur mid-iteration if a page request fails
* For batch processing, implement a retry strategy at the application level if you need finer control than the built-in retry
