# `RintoError`
[🔗](https://github.com/RintoLab/rinto_error/blob/v0.2.0/lib/rinto_error.ex#L1)

Defines an application Error with validated kinds, public payloads, and exception text.

Use the guides for [design](guides/01_design_en.md),
[application usage](guides/02_application_errors_en.md),
[Ecto](guides/03_ecto_en.md), [custom sources](guides/04_custom_structs_en.md),
and [output and logging](guides/05_output_and_logging_en.md).

## Catalog

    defmodule MyApp.Error do
      use RintoError

      catalog do
        entry :local
        entry :missing, http_status: 404
        entry :broken, as: :unavailable, http_status: 503
      end
    end

`entry` declares a constructable internal kind. `entry_for Source, :kind`
also registers an exact struct type; its module must be available at compile
time. Both accept these optional literal values:

* `as:` — public name, defaulting to the internal kind. Mapping happens once;
  output-only names are not constructable unless separately declared.
* `http_status:` — integer from `100` to `599`, looked up by internal kind.
  Missing statuses raise `ArgumentError` only when `http_status/1` is called.
* `doc:` — string included in catalog details, without affecting error behavior.

Kinds and output names must be atom literals other than `nil`, `true`, and
`false`. Variables, module attributes, and computed expressions are rejected,
as are duplicate kinds, source registrations, options, and unknown options.
A module may have one catalog; an empty or omitted catalog accepts no inputs.

`kinds()` lists declared kinds; `kinds(:full)` includes names, statuses, and
docs; `kinds(:public)` groups those details by output name. All preserve declaration
order. `source_kinds()`, `payload_kinds()`, and `statuses()` expose source
registrations, changed output names, and explicitly configured statuses.

## Construction

    require MyApp.Error, as: Error
    Error.new(:missing)
    Error.new(kind: :broken, raw: :db_down, data: %{attempt: 2})

`new/2` constructs an Error and records the call site in `metadata.origin`.
It evaluates input and message once; a non-nil message, including `""`, replaces
the existing message. `exception/1` and `raise Error, opts` do not record origin.

Atom input sets both `kind` and `raw`. Map/keyword input defaults raw to `nil`
and requires kind unless a registered `__source__` supplies it. Unknown fields
raise `KeyError`; missing required fields raise `ArgumentError`. Registered
structs use `RintoError.Source`; unregistered structs raise `ArgumentError`.

Undeclared literal kinds passed directly to `new` fail compilation. Dynamic
inputs and builder results are validated at construction, raising `ArgumentError`
for undeclared kinds. Direct struct construction requires kind and raw but,
like direct map updates, bypasses catalog validation.

## Output

`to_payload/1` returns `%{kind: atom(), data: map(), errors: [term()]}` with the
mapped kind, excluding raw, message, metadata, and the source selector.
Without a source, data and details are emitted as stored. Source conversion
uses `RintoError.Source.to_payload/2`; details are never recursively converted or mapped.

If `JSON.Encoder` or `Jason.Encoder` is loaded when the Error module compiles,
the corresponding implementation is generated and encodes through `to_payload/1`.
The library does not send responses or emit logs.

## Options

* `inspect_opts:` — options for field values in exception text. They merge over
  `config :rinto_error, inspect_opts: [...]`, which merges over defaults
  `[pretty: true, width: 80, limit: :infinity, printable_limit: :infinity]`.
  Application configuration is read per call; module options are captured at
  compile time. Empty lists inherit prior options. This does not affect
  `inspect(error)` or payloads.

Override `message/1` in the Error module to customize exception/log text;
`super(error)` reuses the default formatter. Default text contains kind, message,
data, errors, and metadata, excluding raw and the source selector.

Ecto registration is always explicit. Its standard `RintoError.Source`
implementation follows the same protocol contract as custom sources.
See `RintoError.Source` for implementation and build validation details.

## Generated types

Reference types on your application module, such as `MyApp.Error.t()`:

* `t()` / `t(raw_type)` — Error with arbitrary / specified raw data. The parameter
  constrains raw, not kind; the kind field remains `atom()`.
* `known_kind()` — union of declared internal kinds; `none()` for an empty catalog.
* `payload()` — public output; `kind_detail()` — one catalog declaration.
* `origin()` / `metadata()` — construction location / diagnostic context.

Typespecs do not add runtime checks; construction enforces catalog membership.

## Migrating earlier APIs

Replace positional declarations and `public:`, `expose_as:`, `construct:`, or
`status:` with `entry :kind, as: :name, http_status: 422`. Replace `changeset:` /
`changeset_kind:` with `entry_for Ecto.Changeset, :kind`.
The `use RintoError` options `exclude_default_sources` and `override_sources`
are no longer supported.
To replace the supplied Changeset implementation, configure
`config :rinto_error, exclude_default_sources: [Ecto.Changeset]` before compiling
the dependency, then define your own `defimpl`. Protocol implementations apply
globally per source type; use a wrapper struct for coexisting behaviors.

Replace `expand/2` or two-argument builders with `build/1` returning attributes.
Replace `@behaviour RintoError.Payload` and `to_payload(error)` with the protocol
function `to_payload(_source, error)` in the same `defimpl`. Both protocol
functions are required; the first output argument only selects the source type.
Manual attributes must set `__source__` explicitly
instead of relying on raw's type. Ecto type descriptions now use `t` objects
instead of scalar names or composite `name` keys; see `RintoError.Changeset`.

# `catalog`
*macro* 

Declares this module's error table. A module may have only one `catalog`.
The block may contain only `entry` and `entry_for` calls.

---

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