# `OpenrouterSdk.Error`
[🔗](https://github.com/zmzlois/openrouter_sdk/blob/v0.1.0/lib/openrouter_sdk/error.ex#L1)

uniform error struct returned by every public api function.

`retryable?` is the primary signal consumer middleware should use to
decide whether to back off and try again (or rotate to a different
model/provider). we keep `body` around so callers can inspect the
raw upstream payload when they need to.

# `kind`

```elixir
@type kind() ::
  :transport
  | :timeout
  | :auth
  | :rate_limit
  | :payment_required
  | :invalid_request
  | :server
  | :stream_disconnect
  | :decode
```

# `t`

```elixir
@type t() :: %OpenrouterSdk.Error{
  body: term(),
  code: String.t() | nil,
  kind: kind(),
  message: String.t(),
  retryable?: boolean(),
  status: non_neg_integer() | nil
}
```

# `classify`

```elixir
@spec classify(non_neg_integer(), term()) :: t()
```

classify an http response (status + decoded body) into an error struct.

the status -> kind mapping follows the documented openrouter codes
(400 invalid_request, 401 auth, 402 payment_required, 408 timeout,
429 rate_limit, 5xx server). retry semantics default to: transient
on timeouts / rate limits / server errors, permanent on auth, billing,
validation.

# `decode`

```elixir
@spec decode(binary(), term()) :: t()
```

build an error when a json body fails to decode

# `stream_disconnect`

```elixir
@spec stream_disconnect(term()) :: t()
```

build an error for a stream that disconnected mid-flight

# `transport`

```elixir
@spec transport(term()) :: t()
```

build an error from a transport-layer failure (mint/finch reason term)

---

*Consult [api-reference.md](api-reference.md) for complete listing*
