# Errors and retries

Canonical page: https://docs.ovok.com/flutter-sdk/errors-and-retries

Every failure is an `OvokException` with `status`, `code`, `type`, `message`,
`traceId`, `requestId`, `retryAfterMs` and `fieldErrors`. Catch a subclass to handle
one case:

| Class | When |
|---|---|
| `OvokValidationException` | 400, 422 |
| `OvokAuthenticationException` | 401 |
| `OvokPermissionException` | 403: signed in, but not allowed |
| `OvokNotFoundException` | 404 |
| `OvokConflictException` | 409 |
| `OvokRateLimitException` | 429 |
| `OvokServiceException` | 5xx |
| `OvokConnectionException` | No answer: network failure or timeout |
| `OvokConfigException` | A bad option, or an action this client cannot take |

```dart
try {
  await ovok.fhir.read('Patient', id);
} on OvokNotFoundException {
  // show "not found"
} on OvokException catch (error) {
  log('Ovok failed', error: error.traceId);
}
```

Quote `traceId` when you report a problem.

## Retries and timeouts [#retries-and-timeouts]

- **Retried requests:** GET, PUT, DELETE and conditional creates retry on 429, 502,
  503, 504 or a connection failure, up to `maxNetworkRetries` times.
- **Backoff:** the first wait is 300 ms and doubles each time; `Retry-After` wins, and
  no wait is longer than 5 s.
- **Timeouts:** a timed-out request fails with `OvokConnectionException`.
  `package:http` cannot cancel it, so it may still reach the server.
