# `AshGettext.Error`
[🔗](https://github.com/Undeadlol1/ash_gettext/blob/v0.1.0/lib/ash_gettext/error.ex#L1)

A user-visible failure with a stable `code` and a translatable `message`.

Ash errors carry no code concept, and AshJsonApi hardcodes `code` per error
type, so a client cannot branch on "which rule rejected this" without parsing
a sentence. This struct pairs the two: `code` is what a client switches on,
`message` is the sentence the person reads, written in English. It is the
gettext msgid.

    {:error, AshGettext.Error.exception(
      code: :weight_too_low,
      field: :weight,
      message: "must weigh at least %{min} kg",
      vars: [min: 30]
    )}

## Fields

  * `:code` — required atom; `exception/1` raises `ArgumentError` without it.
  * `:message` — the written sentence, which is the msgid. Left as is when no
    catalog covers it.
  * `:field` — optional; when set, JSON:API points `source.pointer` at it.
  * `:vars` — interpolation values for the translated sentence; JSON:API
    also exposes them as `meta`.

## Translation

`AshGettext.ErrorTranslation.translate/2` translates any struct with a binary
`:message`, so this one needs nothing extra. The translation hook is the
write-action `error_handler` that `AshGettext.Resource` installs, so it only
runs for errors raised from create, update and destroy actions; read and
generic actions return the msgid untranslated.

## Extraction

`mix gettext.extract` finds `message:` given as a literal string in a
resource or in a validation or change module it uses. A message built
anywhere else, or passed as a module attribute or other expression, is not
found: mark it with `dgettext_noop("ash", "...")`.

## JSON:API

When `:ash_json_api` is a dependency, the error renders with its `code` as a
string, the message as `detail`, `vars` as `meta`, and the status of its
class. It has no `title`, so no untranslated English reaches the reader.

# `exception`

```elixir
@spec exception(opts :: Keyword.t()) :: %AshGettext.Error{
  __exception__: term(),
  bread_crumbs: term(),
  class: term(),
  code: term(),
  field: term(),
  message: term(),
  path: term(),
  splode: term(),
  stacktrace: term(),
  vars: term()
}
```

Build the error from `opts`, which must include a `:code`.

Raises `ArgumentError` when `:code` is missing or `nil`. The other fields
are `:message`, `:field` and `:vars`, all optional here.

    AshGettext.Error.exception(code: :weight_too_low, message: "must weigh at least %{min} kg")

# `message`

Return the error's `:message`.

Ash and Elixir call this when they print the error, so an untranslated error
reads as the sentence you wrote.

---

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