# `Sinter.Error`
[🔗](https://github.com/nshkrdotcom/sinter/blob/v0.3.1/lib/sinter/error.ex#L1)

Structured error representation for Sinter validation errors.

This module provides a consistent way to represent validation errors
throughout Sinter, including path information for nested data structures
and machine-readable error codes.

# `t`

```elixir
@type t() :: %Sinter.Error{
  code: atom(),
  context: map() | nil,
  message: String.t(),
  path: [atom() | String.t() | integer()]
}
```

# `filter_by_code`

```elixir
@spec filter_by_code([t()], atom()) :: [t()]
```

Filters errors by error code.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:name], :required, "field is required"),
    ...>   Sinter.Error.new([:age], :type, "expected integer")
    ...> ]
    iex> Sinter.Error.filter_by_code(errors, :required)
    [%Sinter.Error{path: [:name], code: :required, ...}]

# `format`

```elixir
@spec format(
  t(),
  keyword()
) :: String.t()
```

Formats an error into a human-readable string.

## Parameters

  * `error` - The error to format
  * `opts` - Formatting options

## Options

  * `:include_path` - Include the path in the formatted message (default: true)
  * `:path_separator` - Separator for path elements (default: ".")

## Examples

    iex> error = %Sinter.Error{
    ...>   path: [:user, :email],
    ...>   code: :format,
    ...>   message: "invalid email format"
    ...> }
    iex> Sinter.Error.format(error)
    "user.email: invalid email format"

    iex> Sinter.Error.format(error, include_path: false)
    "invalid email format"

# `format_errors`

```elixir
@spec format_errors(
  [t()],
  keyword()
) :: String.t()
```

Formats multiple errors into a readable string.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:name], :required, "field is required"),
    ...>   Sinter.Error.new([:age], :type, "expected integer")
    ...> ]
    iex> Sinter.Error.format_errors(errors)
    "name: field is required\nage: expected integer"

# `group_by_code`

```elixir
@spec group_by_code([t()]) :: %{required(atom()) =&gt; [t()]}
```

Groups errors by their error code.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:name], :required, "field is required"),
    ...>   Sinter.Error.new([:email], :required, "field is required"),
    ...>   Sinter.Error.new([:age], :type, "expected integer")
    ...> ]
    iex> Sinter.Error.group_by_code(errors)
    %{
      required: [
        %Sinter.Error{path: [:name], ...},
        %Sinter.Error{path: [:email], ...}
      ],
      type: [
        %Sinter.Error{path: [:age], ...}
      ]
    }

# `group_by_path`

```elixir
@spec group_by_path([t()]) :: %{required([atom() | String.t() | integer()]) =&gt; [t()]}
```

Groups errors by their path for easier processing.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:user, :name], :required, "field is required"),
    ...>   Sinter.Error.new([:user, :name], :min_length, "too short"),
    ...>   Sinter.Error.new([:user, :email], :format, "invalid format")
    ...> ]
    iex> Sinter.Error.group_by_path(errors)
    %{
      [:user, :name] => [
        %Sinter.Error{code: :required, ...},
        %Sinter.Error{code: :min_length, ...}
      ],
      [:user, :email] => [
        %Sinter.Error{code: :format, ...}
      ]
    }

# `new`

```elixir
@spec new(
  [atom() | String.t() | integer()] | atom() | String.t(),
  atom(),
  String.t(),
  map() | nil
) :: t()
```

Creates a new validation error.

## Parameters

  * `path` - Path to the field that caused the error
  * `code` - Machine-readable error code
  * `message` - Human-readable error message
  * `context` - Optional additional context information

## Examples

    iex> Sinter.Error.new([:user, :email], :format, "invalid email format")
    %Sinter.Error{
      path: [:user, :email],
      code: :format,
      message: "invalid email format",
      context: nil
    }

    iex> Sinter.Error.new(:name, :required, "field is required")
    %Sinter.Error{path: [:name], code: :required, message: "field is required"}

# `summarize`

```elixir
@spec summarize([t()]) :: map()
```

Summarizes validation errors into a report.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:name], :required, "field is required"),
    ...>   Sinter.Error.new([:age], :type, "expected integer"),
    ...>   Sinter.Error.new([:email], :format, "invalid email format")
    ...> ]
    iex> Sinter.Error.summarize(errors)
    %{
      total_errors: 3,
      error_codes: [:required, :type, :format],
      affected_paths: [[:name], [:age], [:email]],
      by_code: %{
        required: 1,
        type: 1,
        format: 1
      }
    }

# `to_map`

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

Converts an error to a map representation.

Useful for JSON serialization or API responses.

## Examples

    iex> error = Sinter.Error.new([:user, :email], :format, "invalid email format")
    iex> Sinter.Error.to_map(error)
    %{
      "path" => ["user", "email"],
      "code" => "format",
      "message" => "invalid email format"
    }

# `to_maps`

```elixir
@spec to_maps([t()]) :: [map()]
```

Converts multiple errors to map representations.

## Examples

    iex> errors = [
    ...>   Sinter.Error.new([:name], :required, "field is required"),
    ...>   Sinter.Error.new([:age], :type, "expected integer")
    ...> ]
    iex> Sinter.Error.to_maps(errors)
    [
      %{"path" => ["name"], "code" => "required", "message" => "field is required"},
      %{"path" => ["age"], "code" => "type", "message" => "expected integer"}
    ]

# `with_context`

```elixir
@spec with_context(
  [atom() | String.t() | integer()] | atom() | String.t(),
  atom(),
  String.t(),
  map()
) :: t()
```

Creates a new error with additional context information.

## Examples

    iex> context = %{expected: "string", actual: "integer", value: 42}
    iex> Sinter.Error.with_context([:age], :type, "expected string", context)
    %Sinter.Error{
      path: [:age],
      code: :type,
      message: "expected string",
      context: %{expected: "string", actual: "integer", value: 42}
    }

# `with_llm_context`

```elixir
@spec with_llm_context(t(), term(), String.t()) :: t()
```

Adds LLM debugging context to a validation error.

This function enhances errors with information about the LLM response and
original prompt, making it easier to debug validation failures in DSPEx
programs.

## Parameters

  * `error` - The original validation error
  * `llm_response` - The raw response from the LLM
  * `prompt` - The original prompt sent to the LLM

## Returns

  * Enhanced error with LLM context information

## Examples

    iex> error = Sinter.Error.new([:name], :required, "field is required")
    iex> llm_response = %{"age" => 30}  # missing name field
    iex> prompt = "Generate a user profile with name and age"
    iex> enhanced = Sinter.Error.with_llm_context(error, llm_response, prompt)
    iex> enhanced.context.llm_response
    %{"age" => 30}
    iex> enhanced.context.prompt
    "Generate a user profile with name and age"

---

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