# Error Recovery

There is no specific demo for error recovery in `examples/` — the framework does the recovery you actually need (gateway reconnect, session resume, heartbeat) automatically inside `Client::start`. What is left to your code is checking the `Result` of each `BotApi` call and deciding whether to log, ignore, or retry.

## What the framework already handles

- WebSocket reconnect with exponential backoff
- Session resume after transient disconnects
- Heartbeat keepalive
- Token validation on `Token::validate()`

You implement `EventHandler::error(&self, error: BotError)` if you want to observe handler-level errors (it has a default impl that just logs). Every demo in `examples/` does exactly this: a one-line `warn!("…: {}", e)`.

## Per-call

`BotApi` methods return `botrs::Result<T>`. The variant you care about is `botrs::BotError`, which already exposes whether the error is transient (network, rate limit) or permanent (auth, malformed payload). Match on it where it matters; otherwise log and move on.

```rust
match message.reply(&ctx.api, &ctx.token, &reply).await {
    Ok(_) => {},
    Err(e) => tracing::warn!("reply failed: {e}"),
}
```

## See also

- Guide: [`docs/guide/error-handling.md`](../guide/error-handling.md) — the canonical reference for `BotError` variants and patterns
- `BotError` definition: `src/error.rs`
