Jido.Signal.Error (Jido Signal v1.0.0)

View Source

Defines error structures and helper functions for Jido

This module provides a standardized way to create and handle errors within the Jido system. It offers a set of predefined error types and functions to create, manipulate, and convert error structures consistently across the application.

Why not use Exceptions?

Jido is designed to be a functional system, strictly adhering to the use of result tuples. This approach provides several benefits:

  1. Consistent error handling: By using {:ok, result} or {:error, reason} tuples, we ensure a uniform way of handling success and failure cases throughout the system.

  2. Composability: Monadic actions can be easily chained together, allowing for cleaner and more maintainable code.

  3. Explicit error paths: The use of result tuples makes error cases explicit, reducing the likelihood of unhandled errors.

  4. No silent failures: Unlike exceptions, which can be silently caught and ignored, result tuples require explicit handling of both success and error cases.

  5. Better testability: Monadic actions are easier to test, as both success and error paths can be explicitly verified.

By using this approach instead of exceptions, we gain more control over the flow of our actions and ensure that errors are handled consistently across the entire system.

Usage

Use this module to create specific error types when exceptions occur in your Jido actions. This allows for consistent error handling and reporting throughout the system.

Example:

defmodule MyExec do
  alias Jido.Signal.Error

  def run(params) do
    case validate(params) do
      :ok -> perform_action(params)
      {:error, reason} -> Error.validation_error("Invalid parameters")
    end
  end
end

Summary

Types

Defines the possible error types in the Jido system.

t()

Represents a structured error in the Jido system.

Functions

Captures the current stacktrace.

Formats a NimbleOptions validation error for configuration validation. Used when validating configuration options at compile or runtime.

Formats a NimbleOptions validation error for parameter validation. Used when validating runtime parameters.

Creates a new error struct with the given type and message.

Converts the error struct to a plain map.

Types

error_type()

@type error_type() ::
  :validation_error
  | :execution_error
  | :planning_error
  | :timeout
  | :routing_error
  | :dispatch_error

Defines the possible error types in the Jido system.

  • :validation_error: Used when input validation fails.
  • :execution_error: Used when an error occurs during action execution.
  • :timeout: Used when an action exceeds its time limit.
  • :planning_error: Used when an error occurs during action planning.
  • :routing_error: Used when an error occurs during action routing.
  • :dispatch_error: Used when an error occurs during signal dispatching.

t()

@type t() :: %Jido.Signal.Error{
  details: map(),
  message: String.t(),
  stacktrace: list(),
  type: error_type()
}

Represents a structured error in the Jido system.

Fields:

  • type: The category of the error (see error_type/0).
  • message: A human-readable description of the error.
  • details: Optional map containing additional error context.
  • stacktrace: Optional list representing the error's stacktrace.

Functions

bad_request(message, details \\ nil, stacktrace \\ nil)

@spec bad_request(String.t(), map() | nil, list() | nil) :: t()

Creates a new bad request error.

Use this when the client sends an invalid or malformed request.

Parameters

  • message: A string describing the error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.bad_request("Missing required parameter 'user_id'")
%Jido.Signal.Error{
  type: :bad_request,
  message: "Missing required parameter 'user_id'",
  details: nil,
  stacktrace: [...]
}

capture_stacktrace()

@spec capture_stacktrace() :: list()

Captures the current stacktrace.

This function is useful when you want to capture the stacktrace at a specific point in your code, rather than at the point where the error is created. It drops the first two entries from the stacktrace to remove internal function calls related to this module.

Returns

The current stacktrace as a list.

Example

iex> stacktrace = Jido.Signal.Error.capture_stacktrace()
iex> is_list(stacktrace)
true

dispatch_error(message, details \\ nil, stacktrace \\ nil)

@spec dispatch_error(String.t(), map() | nil, list() | nil) :: t()

Creates a new dispatch error.

Use this when an error occurs during signal dispatching.

Parameters

  • message: A string describing the dispatch error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.dispatch_error("Failed to deliver signal", %{adapter: :http, reason: :timeout})
%Jido.Signal.Error{
  type: :dispatch_error,
  message: "Failed to deliver signal",
  details: %{adapter: :http, reason: :timeout},
  stacktrace: [...]
}

execution_error(message, details \\ nil, stacktrace \\ nil)

@spec execution_error(String.t(), map() | nil, list() | nil) :: t()

Creates a new execution error.

Use this when an error occurs during the execution of an action.

Parameters

  • message: A string describing the execution error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.execution_error("Failed to process data", %{step: "data_transformation"})
%Jido.Signal.Error{
  type: :execution_error,
  message: "Failed to process data",
  details: %{step: "data_transformation"},
  stacktrace: [...]
}

format_nimble_config_error(error, module_type, module)

@spec format_nimble_config_error(
  NimbleOptions.ValidationError.t() | any(),
  String.t(),
  module()
) :: String.t()

Formats a NimbleOptions validation error for configuration validation. Used when validating configuration options at compile or runtime.

Parameters

  • error: The NimbleOptions.ValidationError to format
  • module_type: String indicating the module type (e.g. "Action", "Agent", "Sensor")

Examples

iex> error = %NimbleOptions.ValidationError{keys_path: [:name], message: "is required"}
iex> Jido.Signal.Error.format_nimble_config_error(error, "Action")
"Invalid configuration given to use Jido.Action for key [:name]: is required"

format_nimble_validation_error(error, module_type, module)

@spec format_nimble_validation_error(
  NimbleOptions.ValidationError.t() | any(),
  String.t(),
  module()
) :: String.t()

Formats a NimbleOptions validation error for parameter validation. Used when validating runtime parameters.

Parameters

  • error: The NimbleOptions.ValidationError to format
  • module_type: String indicating the module type (e.g. "Action", "Agent", "Sensor")

Examples

iex> error = %NimbleOptions.ValidationError{keys_path: [:input], message: "is required"}
iex> Jido.Signal.Error.format_nimble_validation_error(error, "Action")
"Invalid parameters for Action at [:input]: is required"

new(type, message, details \\ nil, stacktrace \\ nil)

@spec new(error_type(), String.t(), map() | nil, list() | nil) :: t()

Creates a new error struct with the given type and message.

This is a low-level function used by other error creation functions in this module. Consider using the specific error creation functions unless you need fine-grained control.

Parameters

  • type: The error type (see error_type/0).
  • message: A string describing the error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Examples

iex> Jido.Signal.Error.new(:config_error, "Invalid configuration")
%Jido.Signal.Error{
  type: :config_error,
  message: "Invalid configuration",
  details: nil,
  stacktrace: [...]
}

iex> Jido.Signal.Error.new(:execution_error, "Exec failed", %{step: "data_processing"})
%Jido.Signal.Error{
  type: :execution_error,
  message: "Exec failed",
  details: %{step: "data_processing"},
  stacktrace: [...]
}

routing_error(message, details \\ nil, stacktrace \\ nil)

@spec routing_error(String.t(), map() | nil, list() | nil) :: t()

Creates a new routing error.

Use this when an error occurs during action routing.

Parameters

  • message: A string describing the routing error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.routing_error("Invalid route configuration", %{route: "user_action"})
%Jido.Signal.Error{
  type: :routing_error,
  message: "Invalid route configuration",
  details: %{route: "user_action"},
  stacktrace: [...]
}

timeout(message, details \\ nil, stacktrace \\ nil)

@spec timeout(String.t(), map() | nil, list() | nil) :: t()

Creates a new timeout error.

Use this when an action exceeds its allocated time limit.

Parameters

  • message: A string describing the timeout error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.timeout("Exec timed out after 30 seconds", %{action: "FetchUserData"})
%Jido.Signal.Error{
  type: :timeout,
  message: "Exec timed out after 30 seconds",
  details: %{action: "FetchUserData"},
  stacktrace: [...]
}

to_map(error)

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

Converts the error struct to a plain map.

This function transforms the error struct into a plain map, including the error type and stacktrace if available. It's useful for serialization or when working with APIs that expect plain maps.

Parameters

  • error: An error struct of type t/0.

Returns

A map representation of the error.

Example

iex> error = Jido.Signal.Error.validation_error("Invalid input")
iex> Jido.Signal.Error.to_map(error)
%{
  type: :validation_error,
  message: "Invalid input",
  stacktrace: [...]
}

validation_error(message, details \\ nil, stacktrace \\ nil)

@spec validation_error(String.t(), map() | nil, list() | nil) :: t()

Creates a new validation error.

Use this when input validation fails for an action.

Parameters

  • message: A string describing the validation error.
  • details: (optional) A map containing additional error details.
  • stacktrace: (optional) The stacktrace at the point of error.

Example

iex> Jido.Signal.Error.validation_error("Invalid email format", %{field: "email", value: "not-an-email"})
%Jido.Signal.Error{
  type: :validation_error,
  message: "Invalid email format",
  details: %{field: "email", value: "not-an-email"},
  stacktrace: [...]
}