# `Jido.Error`
[🔗](https://github.com/agentjido/jido/blob/v2.3.0/lib/jido/error.ex#L1)

Unified error handling for the Jido ecosystem using Splode.

## Error Types

Six consolidated error types cover all failure scenarios:

| Error | Use Case |
|-------|----------|
| `ValidationError` | Invalid inputs, actions, sensors, configs |
| `ExecutionError` | Runtime failures during execution or planning |
| `RoutingError` | Signal routing and dispatch failures |
| `TimeoutError` | Operation timeouts |
| `CompensationError` | Saga compensation failures |
| `InternalError` | Unexpected system failures |

## Usage

    # Validation failures (with optional kind)
    Jido.Error.validation_error("Invalid email", kind: :input, field: :email)
    Jido.Error.validation_error("Unknown action", kind: :action, action: MyAction)

    # Execution failures (with optional phase)
    Jido.Error.execution_error("Action failed", phase: :run)
    Jido.Error.execution_error("Planning failed", phase: :planning)

    # Routing/dispatch failures
    Jido.Error.routing_error("No handler", target: "user.created")

    # Timeouts
    Jido.Error.timeout_error("Timed out", timeout: 5000)

    # Internal errors
    Jido.Error.internal_error("Unexpected failure")

## Splode Error Classes

Errors are classified for aggregation (in order of precedence):
- `:invalid` - Validation failures
- `:execution` - Runtime failures
- `:routing` - Routing/dispatch failures
- `:timeout` - Timeouts
- `:internal` - Unexpected failures

# `class`

```elixir
@type class() :: %{
  :__struct__ =&gt; class_module(),
  :__exception__ =&gt; true,
  :errors =&gt; [t()],
  :class =&gt; error_class(),
  :bread_crumbs =&gt; [String.t()],
  :vars =&gt; Keyword.t(),
  :stacktrace =&gt; Splode.Stacktrace.t() | nil,
  :context =&gt; map(),
  optional(atom()) =&gt; any()
}
```

# `class_module`

```elixir
@type class_module() ::
  Jido.Error.Internal
  | Jido.Error.Timeout
  | Jido.Error.Routing
  | Jido.Error.Execution
  | Jido.Error.Invalid
  | Splode.Error.Unknown
```

# `error_class`

```elixir
@type error_class() ::
  :internal | :timeout | :routing | :execution | :invalid | :unknown
```

# `t`

```elixir
@type t() :: %{
  :__struct__ =&gt; module(),
  :__exception__ =&gt; true,
  :class =&gt; error_class(),
  :bread_crumbs =&gt; [String.t()],
  :vars =&gt; Keyword.t(),
  :stacktrace =&gt; Splode.Stacktrace.t() | nil,
  :context =&gt; map(),
  optional(atom()) =&gt; any()
}
```

# `compensation_error`

```elixir
@spec compensation_error(String.t(), keyword() | map()) ::
  Jido.Error.CompensationError.t()
```

Creates a compensation error.

## Options

- `:original_error` - The error that triggered compensation
- `:compensated` - Whether compensation succeeded (default: false)
- `:result` - Result from successful compensation
- `:details` - Additional context map

# `execution_error`

```elixir
@spec execution_error(String.t(), keyword() | map()) :: Jido.Error.ExecutionError.t()
```

Creates an execution error.

## Options

- `:phase` - Where failure occurred: `:execution`, `:planning`
- `:details` - Additional context map
- Any other keys are merged into `details`

# `extract_message`

```elixir
@spec extract_message(any()) :: String.t()
```

Extracts the message string from a nested error structure.

# `format_nimble_config_error`

```elixir
@spec format_nimble_config_error(any(), String.t(), module()) :: String.t()
```

Formats a NimbleOptions configuration error.

# `format_nimble_validation_error`

```elixir
@spec format_nimble_validation_error(any(), String.t(), module()) :: String.t()
```

Formats a NimbleOptions validation error for parameters.

# `internal_error`

```elixir
@spec internal_error(String.t(), keyword() | map()) :: Jido.Error.InternalError.t()
```

Creates an internal error.

## Options

- `:details` - Additional context map

# `retryable?`

```elixir
@spec retryable?(term()) :: boolean()
```

Returns whether an error is safe to retry by default.

Explicit `:retry`, `:retryable`, and `:retryable?` boolean hints in structured
details override the default classification.

# `routing_error`

```elixir
@spec routing_error(String.t(), keyword() | map()) :: Jido.Error.RoutingError.t()
```

Creates a routing error.

## Options

- `:target` - The intended routing target
- `:details` - Additional context map

# `splode_error?`

# `timeout_error`

```elixir
@spec timeout_error(String.t(), keyword() | map()) :: Jido.Error.TimeoutError.t()
```

Creates a timeout error.

## Options

- `:timeout` - The timeout value in milliseconds
- `:details` - Additional context map

# `to_map`

```elixir
@spec to_map(any()) :: map()
```

Converts an error into a stable, public map.

The returned map is suitable for transport and reporting boundaries. It
includes bounded, sanitized details and never includes stacktraces by default.

# `traverse_errors`

Traverses errors, calling `fun` for each leaf error, and returns a nested
map of results grouped by each error's `path`.

See `Splode.traverse_errors/2` for full documentation.

## Example

    iex> Elixir.Jido.Error.traverse_errors(error, fn error ->
    ...>   Exception.message(error)
    ...> end)
    %{name: ["name is required"]}

# `unwrap!`

Raises an error if the result is an error, otherwise returns the result

Alternatively, you can use the `defsplode` macro, which does this automatically.

### Options

- `:error_opts` - Options to pass to `to_error/2` when converting the returned error
- `:unknown_error_opts` - Options to pass to the unknown error if the function returns only `:error`.
  not necessary if your function always returns `{:error, error}`.

### Examples

  def function(arg) do
    case do_something(arg) do
      :success -> :ok
      {:success, result} -> {:ok, result}
      {:error, error} -> {:error, error}
    end
  end

  def function!(arg) do
    YourErrors.unwrap!(function(arg))
  end

# `validation_error`

```elixir
@spec validation_error(String.t(), keyword() | map()) ::
  Jido.Error.ValidationError.t()
```

Creates a validation error.

## Options

- `:kind` - Category: `:input`, `:action`, `:sensor`, `:config`
- `:subject` - The invalid value
- `:field` - Alias for `:subject` (for input validation)
- `:action` - Alias for `:subject` with `kind: :action`
- `:sensor` - Alias for `:subject` with `kind: :sensor`
- `:details` - Additional context map

## Examples

    validation_error("Invalid email", field: :email)
    validation_error("Unknown action", kind: :action, subject: MyAction)

