View Source Ash.Error (ash v2.9.20)

Tools and utilities used by Ash to manage and conform errors

Link to this section Summary

Link to this section Types

@type error_class() :: :forbidden | :invalid | :framework | :unknown
@type t() :: %{
  :__struct__ => module(),
  :__exception__ => true,
  :class => error_class(),
  :path => [atom() | integer()],
  :changeset => Ash.Changeset.t() | nil,
  :query => Ash.Query.t() | nil,
  :error_context => [String.t()],
  :vars => Keyword.t(),
  :stacktrace => Ash.Error.Stacktrace.t() | nil,
  optional(atom()) => any()
}

Link to this section Functions

Link to this function

choose_error(errors, changeset_or_query \\ nil)

View Source
Link to this function

clear_stacktraces(error)

View Source
Link to this function

error_descriptions(errors)

View Source
Link to this function

error_messages(errors, custom_message, stacktraces?)

View Source
Link to this function

flatten_preserving_keywords(list)

View Source

A utility to flatten a list, but preserve keyword list elements

Link to this function

to_ash_error(list, stacktrace \\ nil, opts \\ [])

View Source

Converts a term into an Ash Error.

The term could be a simple string, the second element in an {:error, error} tuple, an Ash Error, or a list of any of these. In most cases the returned error is an Ash.Error.Unknown.UnknownError.

A stacktrace is added to the error, and any existing stacktrace (i.e. when the term is an Ash Error) is preserved.

to_ash_error converts string(s) into UnknownError(s):

  iex(1)> Ash.Error.to_ash_error("whoops!", nil, error_context: "some context")
  %Ash.Error.Unknown.UnknownError{
    changeset: nil,
    class: :unknown,
    error: "whoops!",
    error_context: ["some context"],
    field: nil,
    path: [],
    query: nil,
    stacktrace: #Stacktrace<>,
    vars: []
  }

  iex(2)> Ash.Error.to_ash_error(["whoops!", "whoops, again!!"], nil, error_context: "some context")
  [
    %Ash.Error.Unknown.UnknownError{
      changeset: nil,
      class: :unknown,
      error: "whoops!",
      error_context: ["some context"],
      field: nil,
      path: [],
      query: nil,
      stacktrace: #Stacktrace<>,
      vars: []
    },
    %Ash.Error.Unknown.UnknownError{
      changeset: nil,
      class: :unknown,
      error: "whoops, again!!",
      error_context: ["some context"],
      field: nil,
      path: [],
      query: nil,
      stacktrace: #Stacktrace<>,
      vars: []
    }
  ]

to_ash_error can preserve error-like data from a keyword-list and accumulate context if called against an Ash Error:

  iex(1)> err = Ash.Error.to_ash_error([vars: [:some_var], message: "whoops!"], nil, error_context: " some context")
  %Ash.Error.Unknown.UnknownError{
    changeset: nil,
    class: :unknown,
    error: "whoops!",
    error_context: ["some context"],
    field: nil,
    path: [],
    query: nil,
    stacktrace: #Stacktrace<>,
    vars: [:some_var]
  }
  iex(2)> Ash.Error.to_ash_error(err, nil, error_context: "some higher context")
  %Ash.Error.Unknown.UnknownError{
    changeset: nil,
    class: :unknown,
    error: "whoops!",
    error_context: ["some higher context", "some context"],
    field: nil,
    path: [],
    query: nil,
    stacktrace: #Stacktrace<>,
    vars: [:some_var]
  }

Options:

  • error_context: a sting message providing extra context around the error
Link to this function

to_error_class(values, opts \\ [])

View Source

Conforms a term into one of the built-in Ash Error classes.

The provided term would usually be an Ash Error or a list of Ash Errors.

If the term is:

  • a map/struct/Ash Error with a key :class having a value :special,
  • a list with a single map/struct/Ash Error element as above, or
  • an Ash.Error.Invalid containing such a list in its :errors field

then the term is returned unchanged.

Example:


iex(1)> Ash.Error.to_error_class("oops", changeset: Ash.Changeset.new(%Post{}), error_context: "some context")
  %Ash.Error.Unknown{
    changeset: #Ash.Changeset<
      errors: [
        %Ash.Error.Unknown.UnknownError{
          changeset: nil,
          class: :unknown,
          error: "oops",
          error_context: ["some context"],
          field: nil,
          path: [],
          query: nil,
          stacktrace: #Stacktrace<>,
          vars: []
        }
      ],
      ...
    >,
    class: :unknown,
    error_context: ["some context"],
    errors: [
      %Ash.Error.Unknown.UnknownError{
        changeset: nil,
        class: :unknown,
        error: "oops",
        error_context: ["some context"],
        field: nil,
        path: [],
        query: nil,
        stacktrace: #Stacktrace<>,
        vars: []
      }
    ],
    stacktrace: #Stacktrace<>,
    stacktraces?: true,
    vars: []
  }

Example of nested errors:

  iex(1)> error1 = Ash.Error.to_ash_error("whoops!", nil, error_context: "some context")
  iex(2)> error2 = Ash.Error.to_ash_error("whoops, again!!", nil, error_context: "some other context")
  iex(3)> Ash.Error.to_error_class([error1, error2], error_context: "some higher context")
  %Ash.Error.Unknown{
    changeset: nil,
    class: :unknown,
    error_context: ["some higher context"],
    errors: [
      %Ash.Error.Unknown.UnknownError{
        changeset: nil,
        class: :unknown,
        error: "whoops!",
        error_context: ["some higher context", "some context"],
        field: nil,
        path: [],
        query: nil,
        stacktrace: #Stacktrace<>,
        vars: []
      },
      %Ash.Error.Unknown.UnknownError{
        changeset: nil,
        class: :unknown,
        error: "whoops, again!!",
        error_context: ["some higher context", "some other context"],
        field: nil,
        path: [],
        query: nil,
        stacktrace: #Stacktrace<>,
        vars: []
      }
    ],
    path: [],
    query: nil,
    stacktrace: #Stacktrace<>,
    stacktraces?: true,
    vars: []
  }

Options:

  • changeset: a changeset related to the error
  • query: a query related to the error
  • error_context: a sting message providing extra context around the error