# Errors And Config Reference
Jidoka funnels every runtime-facing error through `Jidoka.Error` (a Splode
front end) and reads every default through `Jidoka.Config`. This reference
guide documents the error classes, the canonical helpers, and the full
defaults table. Use it when wiring telemetry, building app-facing error
formatters, or tuning application config.
## When To Use This
- Use this guide when you need to know the exact shape and category of a
Jidoka error in logs, telemetry, or HTTP responses.
- Use this guide when you are configuring Jidoka defaults under `:jidoka` in
your application config.
- Do not use this guide as a general onboarding doc; see
[Getting Started](getting-started.md).
## Prerequisites
- You can compile and run the `:jidoka` test suite.
- You have basic familiarity with the Splode error library.
## Quick Example
Normalizing an arbitrary failure and turning it into wire data is two calls.
```elixir
case Jidoka.turn(MyApp.TimeAgent, "Hello") do
{:ok, result} ->
result
{:error, reason} ->
error = Jidoka.normalize_error(reason, phase: :turn)
Jidoka.format_error(error)
#=> "Jidoka execution failed."
Jidoka.error_to_map(error)
#=> %{category: :execution, message: "Jidoka execution failed.", phase: :turn, details: %{...}}
end
```
The same helpers are exported as [`Jidoka.Error.normalize/2`](`Jidoka.Error`),
`Jidoka.Error.format/1`, and `Jidoka.Error.to_map/1` for direct use inside the
package.
## Concepts
```diagram
╭──────────────╮ ╭─────────────────╮ ╭────────────────╮
│ raw reason │────▶│ Jidoka.Error │────▶│ Splode error │
│ (atom, map, │ │ .normalize/2 │ │ class struct │
│ exception) │ ╰─────────────────╯ ╰────────┬───────╯
╰──────────────╯ │
▼
╭──────────────────╮
│ Error.format/1 │
│ Error.to_map/1 │
╰──────────────────╯
```
Splode error **classes** are buckets that group together specific error
structs. Every public Jidoka API returns either an `:ok` tuple or one of the
four classes.
## Fields
### Error Classes
| Class | Module | Splode `class` | Purpose |
| --- | --- | --- | --- |
| Invalid input / validation | [`Jidoka.Error.Invalid`](`Jidoka.Error.Invalid`) | `:invalid` | Callers passed bad data (missing input, invalid context, unsupported version). |
| Execution | [`Jidoka.Error.Execution`](`Jidoka.Error.Execution`) | `:execution` | Runtime-side failure (timeout, exceeded turns, capability returned `{:error, _}`). |
| Configuration | [`Jidoka.Error.Config`](`Jidoka.Error.Config`) | `:config` | App-level misconfiguration (missing module, invalid schema). |
| Internal | internal error wrapper | `:internal` | Unknown or unexpected failures wrapped as an internal unknown error. |
Each class is a Splode error class with an `errors:` list of one or more
concrete error structs (`ValidationError`, `ConfigError`, `ExecutionError`,
or `Internal.UnknownError`).
### Error Structs
| Struct | Fields | Used for |
| --- | --- | --- |
| `Jidoka.Error.ValidationError` | `:message`, `:field`, `:value`, `:details` | Invalid inputs (missing input, bad context, unknown agent). |
| `Jidoka.Error.ConfigError` | `:message`, `:field`, `:value`, `:details` | Config issues (missing agent module, invalid handler arity). |
| `Jidoka.Error.ExecutionError` | `:message`, `:phase`, `:details` | Runtime failures (turn timeout, exceeded turns, capability errors). |
| internal unknown error | `:message`, `:details`, `:error` | Catch-all for unexpected terms. |
`Jidoka.Error.validation_error/2`, `config_error/2`, and `execution_error/2`
are the canonical constructors. They take a message and either a keyword list
or map of details; the `:details` map is sanitized before any rendering.
### Public Helpers
The four most important error helpers, exported from both `Jidoka.Error` and
the top-level `Jidoka` facade:
| Helper | Returns | Use |
| --- | --- | --- |
| `Jidoka.normalize_error/2` | exception | Turn any reason (atom, tuple, struct) into a Jidoka/Splode exception. |
| `Jidoka.format_error/1` | string | Short, human-readable summary suitable for logs or UI. |
| `Jidoka.error_to_map/1` | map | JSON-friendly map with `:category`, `:message`, and structured details. |
| `Jidoka.Error.category/1` | `:validation \| :configuration \| :execution \| :internal \| :unknown` | Classify an already-normalized error. |
The `format/1` and `to_map/1` helpers automatically redact secret-like fields
(`api_key`, `authorization`, `password`, `secret`, `token`) and omit
high-cardinality fields (`messages`, `prompt`, `request_body`, etc.).
### `Jidoka.Config` Defaults
`Jidoka.Config` reads every default through `Application.get_env(:jidoka, key, fallback)`
and validates the value before returning.
| Helper | Config key (under `:jidoka`) | Fallback | Validator |
| --- | --- | --- | --- |
| `Jidoka.Config.default_model/0` | `:default_model` | `"openai:gpt-4o-mini"` | `normalize_model_spec!/2` (ReqLLM input). |
| `Jidoka.Config.default_generation/0` | `:default_generation` | `%{params: %{temperature: 0.0, max_tokens: 500}}` | `normalize_generation!/2`. |
| `Jidoka.Config.default_max_model_turns/0` | `:default_max_model_turns` | `8` | `normalize_positive_integer!/2`. |
| `Jidoka.Config.default_turn_timeout_ms/0` | `:default_turn_timeout_ms` | `30_000` | `normalize_positive_integer!/2`. |
Example application configuration:
```elixir
# config/config.exs
import Config
config :jidoka,
default_model: "anthropic:claude-3-5-sonnet-latest",
default_generation: %{params: %{temperature: 0.2, max_tokens: 1_024}},
default_max_model_turns: 6,
default_turn_timeout_ms: 45_000
```
Two additional `Jidoka.Config` helpers are worth knowing:
| Helper | Purpose |
| --- | --- |
| `Jidoka.Config.normalize_model_spec/2` | Validate any ReqLLM-supported model input without raising. |
| `Jidoka.Config.model_ref/1` | Render an `%LLMDB.Model{}` (or any input) back to a `"provider:id"` string for prompts, logs, and tests. |
## Common Patterns
- **Always normalize before logging.** Raw atoms or tuples lose context;
`Jidoka.normalize_error/2` adds a category, message, and phase.
- **Use `error_to_map/1` at the wire boundary.** It is JSON-safe and applies
secret redaction automatically.
- **Set defaults in config, not in agents.** `spec` overrides win, but
`:jidoka` defaults are what unify behavior across modules.
- **Treat `:invalid` as a 4xx and `:execution` as a 5xx.** Mapping
`Jidoka.Error.category/1` directly to HTTP status codes works well in
practice.
## Testing
Error tests are most useful when they assert on both the category and the
relevant detail.
```elixir
test "missing input becomes a validation error" do
error = Jidoka.normalize_error(:missing_input)
assert Jidoka.Error.category(error) == :validation
assert %{category: :validation, message: message} = Jidoka.error_to_map(error)
assert message =~ "input is required"
end
test "config defaults round-trip" do
Application.put_env(:jidoka, :default_max_model_turns, 12)
assert Jidoka.Config.default_max_model_turns() == 12
after
Application.delete_env(:jidoka, :default_max_model_turns)
end
```
## Troubleshooting
| Symptom | Likely Cause | Fix |
| --- | --- | --- |
| `ArgumentError: invalid default_model: ...` at boot | `:jidoka, :default_model` is not a valid ReqLLM input. | Use a `"provider:id"` string or a `%LLMDB.Model{}` struct. |
| Error map shows `category: :unknown` | The reason was never normalized. | Pipe through `Jidoka.normalize_error/2` first. |
| Logs leak API keys or large prompts | Direct `inspect/1` on the raw error. | Use `Jidoka.format_error/1` or `Jidoka.error_to_map/1`; both sanitize. |
| `{:error, {:turn_timeout_exceeded, _, _}}` rendered as a generic message | Helper not used. | `Jidoka.normalize_error/2` adds `phase: :turn` and structured details. |
| New error reason renders as `Jidoka execution failed.` | No dedicated normalizer matched. | That is the default Execution fallback; either add a specific normalizer or include the cause via the `context` argument. |
## Reference
- [`Jidoka.Error`](`Jidoka.Error`) - Splode entry point and helpers.
- [`Jidoka.Error.Invalid`](`Jidoka.Error.Invalid`) - validation error class.
- [`Jidoka.Error.Execution`](`Jidoka.Error.Execution`) - execution error
class.
- [`Jidoka.Error.Config`](`Jidoka.Error.Config`) - configuration error class.
- [`Jidoka.Error.Internal`](`Jidoka.Error.Internal`) - internal error class
(and `Internal.UnknownError`).
- [`Jidoka.Error.ValidationError`](`Jidoka.Error.ValidationError`),
[`Jidoka.Error.ConfigError`](`Jidoka.Error.ConfigError`),
[`Jidoka.Error.ExecutionError`](`Jidoka.Error.ExecutionError`).
- [`Jidoka.Config`](`Jidoka.Config`) - `default_model/0`,
`default_generation/0`, `default_max_model_turns/0`,
`default_turn_timeout_ms/0`, `normalize_model_spec/2`, `model_ref/1`.
## Related Guides
- [Getting Started](getting-started.md) - first encounter with defaults.
- [Agent Spec Contract](agent-spec-contract.md) - where `Spec` consumes
`Jidoka.Config` defaults.
- [Turn And Effect Contracts](turn-and-effect-contracts.md) - the runtime
phases that produce execution errors.
- [Runtime And Harness](runtime-and-harness.md) - where harness-side errors
originate.