# `ALLM.Error.SessionError`
[🔗](https://github.com/cykod/ALLM/blob/v0.3.0/lib/allm/error/session_error.ex#L1)

Session-state error. Returned (or raised) by Phase 8's `ALLM.Session`
operations.

Layer A — serializable (no PIDs, refs, funs, or raw API keys). Refines
spec §20's atom taxonomy into a first-class struct so every Layer D
public function can return `{:error, %ALLM.Error.SessionError{}}`
uniformly.

See `steering/PHASE_8_DESIGN.md` §"Atom vocabulary additions" for the
closed reason enum and the §"Error Contract" table for the recovery
guidance per reason.

## Reasons

| Reason | Fires when |
|--------|------------|
| `:session_in_error_state` | Caller invokes a Phase-8 operation on a `%Session{status: :error}`. |
| `:invalid_status_for_operation` | Reserved for future use (currently unused — Decision #7 routes status mismatches to `ArgumentError`). |
| `:no_pending_tool_call` | Reserved for future use; the Phase-8 status guard catches this case via `ArgumentError`. |
| `:unknown_tool_call_id` | `submit_tool_result/3` or `submit_tool_results/2` received a `tool_call_id` that does not match any pending `%ToolCall{}` on the session. Data validation, NOT a programmer-flow error. |

# `reason`

```elixir
@type reason() ::
  :session_in_error_state
  | :invalid_status_for_operation
  | :no_pending_tool_call
  | :unknown_tool_call_id
```

Closed set of session-level error reasons (spec §20).

# `t`

```elixir
@type t() :: %ALLM.Error.SessionError{
  __exception__: true,
  cause: term() | nil,
  message: String.t(),
  metadata: map(),
  provider: nil,
  reason: reason()
}
```

# `new`

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

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

`opts` may include `:message`, `:cause`, and `:metadata`. `:provider` is
always `nil` for session errors (session is a Layer D concept; no
provider context is meaningful). When `:message` is omitted, it
defaults to `"session error: #{reason}"`.

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

## Examples

    iex> err = ALLM.Error.SessionError.new(:session_in_error_state)
    iex> err.reason
    :session_in_error_state
    iex> Exception.message(err)
    "session error: session_in_error_state"

    iex> err = ALLM.Error.SessionError.new(:unknown_tool_call_id, metadata: %{tool_call_id: "c0"})
    iex> err.metadata
    %{tool_call_id: "c0"}

---

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