defmodule CircleCI.Error do @moduledoc """ Exception struct used for communicating errors from the client > #### Note {:.info} > > Functions in this module is unlikely to be used directly by applications. Instead, they are > useful for plugins. See `CircleCI.Plugin` for more information. This error covers errors generated by the client (for example, HTTP connection errors) as well as errors returned from the CircleCI API (for example, Not Found errors). ## Fields * `code` (integer): Status code of the API response, if a response was received. * `message` (string): Human-readable message describing the error. Defaults to a generic `"Unknown Error"`. * `operation` (`t:Operation.t/0`): Operation at the time of the error. * `reason` (atom): Easily-matched atom for common errors, like `:not_found`. Defaults to a generic `:error`. See **Error Reasons** below for a list of possible values. * `source` (term): Cause of the error. This could be an operation, an API error response, or something else. * `stacktrace` (`t:Exception.stacktrace/0`): Stacktrace from the time of the error. Defaults to a stack that terminates with the calling function, but can be overridden (for example, if a `__STACKTRACE__` is available in a `rescue` block). * `step` (plugin): Plugin active at the time of the error (expressed as a tuple containing the module and function). Users of the library can match on the information in the `code` and `source` fields to extract additional information. ## Error Reasons Although plugins may use any atom for the `reason` field, the following have predetermined meanings: * `:invalid_auth`: The credential (`:auth` option) provided is invalid. * `:invalid_version`: The version (`:version` option) provided is invalid. * `:not_found`: A resource or route was not found. Note that CircleCI may return this kind of response when authentication is required to see a resource. * `:oauth_restricted`: The OAuth credentials are valid, but the requested resource is owned by an organization that requires admin approval for OAuth apps. * `:rate_limited`: The client has exceeded a primary or secondary rate limit. Secondary rate limits have a distinct `message` field with further information. * `:requires_auth`: The requested endpoint requires an authenticated user, and no auth credentials were given. * `:unauthorized`: Valid authentication credentials were given, but the current user does not have permission to perform this action. """ alias CircleCI.Operation @typedoc "CircleCI API client error" @type t :: %__MODULE__{ code: integer | nil, message: String.t(), operation: Operation.t(), reason: atom, source: term, stacktrace: Exception.stacktrace(), step: {module, atom} } @derive {Inspect, except: [:operation, :stacktrace]} defexception [:code, :message, :operation, :reason, :source, :stacktrace, :step] @doc """ Create a new error struct with the given fields The current stacktrace is automatically filled in to the resulting error. Callers should specify the status `code` (if available), a `message`, the original `operation`, the `source` of the error, and which `step` or plugin is currently active. """ @spec new(keyword) :: t def new(opts) do {:current_stacktrace, stack} = Process.info(self(), :current_stacktrace) # Drop `Process.info/2` and `new/1`. stacktrace = Enum.drop(stack, 2) fields = Keyword.merge( [ message: "Unknown Error", reason: :error, stacktrace: stacktrace ], opts ) struct!(%__MODULE__{}, fields) end end