# `ALLM.Error.TranscriptionAdapterError`
[🔗](https://github.com/cykod/ALLM/blob/v0.6.1/lib/allm/error/transcription_adapter_error.ex#L1)

Errors returned by transcription adapters.

Layer A — serializable (no PIDs, refs, funs, or raw API keys). A
closed-enum exception struct with eleven reasons: the ten that
`ALLM.Error.SpeechAdapterError` carries, plus `:content_filter`.

There is no `:batch_too_large`: a transcription request carries one clip,
and there is no multi-input form to overflow.

## Error reasons

| Reason | HTTP status | Fires when |
|--------|-------------|------------|
| `:authentication_failed` | 401/403 | API key missing or invalid. Surface to the user; no retry. |
| `:rate_limited` | 429 | Provider quota exceeded; `:retry_after_ms` populated when a `Retry-After` header is present. Retried automatically. |
| `:invalid_request` | 400/404/413 | Request shape rejected, or audio the adapter cannot send: unresolvable (a missing file, invalid base64), over the provider's size cap, or of a type it does not accept. `:metadata` carries the detail (`:count`, `:max`, `:cause`). Fix the request; no retry. |
| `:context_length_exceeded` | 400 | The audio exceeds the model's token window. Shorten the clip; no retry. |
| `:content_filter` | 200/400 | The provider's safety system blocked the transcript. No retry. |
| `:provider_unavailable` | 5xx | Provider server-side failure. Retried automatically. |
| `:timeout` | — | Adapter `request_timeout` exceeded. Retried automatically. |
| `:network_error` | — | TCP/TLS/DNS failure. Retried automatically. |
| `:malformed_response` | — | 200 without the expected transcript text. No retry; file a bug. |
| `:unsupported_feature` | — | The request sets a field the adapter's provider cannot express (for example a `:prompt` the provider has no field for). Refused locally, before the API key is resolved. Drop the field; no retry. Also returned after a successful call when a requested `timestamps: true` / `logprobs: true` finds no span data (word timings or log-probabilities) in the provider's response and the transcript is not blank: `metadata.cause` is `:absent_from_response`, `metadata.field` names the flag, and `metadata.text` carries the transcript. |
| `:unknown` | any | Catch-all for shapes the adapter cannot classify; non-retryable. |

# `reason`

```elixir
@type reason() ::
  :authentication_failed
  | :rate_limited
  | :invalid_request
  | :context_length_exceeded
  | :provider_unavailable
  | :timeout
  | :network_error
  | :malformed_response
  | :content_filter
  | :unsupported_feature
  | :unknown
```

Closed set of transcription-adapter error reasons.

# `t`

```elixir
@type t() :: %ALLM.Error.TranscriptionAdapterError{
  __exception__: true,
  cause: term() | nil,
  message: String.t(),
  metadata: map(),
  provider: atom() | nil,
  reason: reason(),
  retry_after_ms: non_neg_integer() | nil,
  status: pos_integer() | nil
}
```

# `legal_reasons`

```elixir
@spec legal_reasons() :: [reason()]
```

Return the closed list of legal `:reason` atoms.

## Examples

    iex> :content_filter in ALLM.Error.TranscriptionAdapterError.legal_reasons()
    true

    iex> :unsupported_feature in ALLM.Error.TranscriptionAdapterError.legal_reasons()
    true

    iex> length(ALLM.Error.TranscriptionAdapterError.legal_reasons())
    11

# `new`

```elixir
@spec new(
  reason(),
  keyword()
) :: t()
```

Build a `%TranscriptionAdapterError{}` from a `reason` atom and optional keyword
fields.

`opts` may include `:message`, `:provider`, `:status`, `:retry_after_ms`,
`:cause`, and `:metadata`. When `:message` is omitted, the default is
`"transcription adapter error: #{reason}"` — with a provider suffix
`"transcription adapter error (#{provider}): #{reason}"` when `:provider` is
set.

Raises `ArgumentError` if `reason` is not one of the atoms in the closed
`t:reason/0` enum.

## Examples

    iex> err = ALLM.Error.TranscriptionAdapterError.new(:timeout)
    iex> err.reason
    :timeout
    iex> Exception.message(err)
    "transcription adapter error: timeout"

    iex> err = ALLM.Error.TranscriptionAdapterError.new(:invalid_request, metadata: %{count: 30_000_000, max: 25_000_000})
    iex> err.metadata.max
    25000000

---

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