Packages

Elixir client library for the Alpaca Trading API. Supports trading, market data, and account management.

Current section

Files

Jump to
alpa_ex lib alpa error.ex
Raw

lib/alpa/error.ex

defmodule Alpa.Error do
@moduledoc """
Error types for the Alpa client.
All API errors are wrapped in an `Alpa.Error` struct with
structured information about what went wrong.
"""
@type t :: %__MODULE__{
type: error_type(),
message: String.t(),
code: integer() | nil,
details: map() | nil
}
@type error_type ::
:unauthorized
| :forbidden
| :not_found
| :unprocessable_entity
| :rate_limited
| :server_error
| :network_error
| :timeout
| :invalid_response
| :missing_credentials
| :unknown
defstruct [:type, :message, :code, :details]
@doc """
Create an error from an HTTP response.
"""
@spec from_response(integer(), map() | String.t()) :: t()
def from_response(status, body) when is_map(body) do
%__MODULE__{
type: type_from_status(status),
message: Map.get(body, "message", "Unknown error"),
code: Map.get(body, "code") || status,
details: body
}
end
def from_response(status, body) when is_binary(body) do
%__MODULE__{
type: type_from_status(status),
message: body,
code: status,
details: nil
}
end
@doc """
Create a network/connection error.
"""
@spec network_error(term()) :: t()
def network_error(reason) do
%__MODULE__{
type: :network_error,
message: "Network error: #{inspect(reason)}",
code: nil,
details: %{reason: reason}
}
end
@doc """
Create a timeout error.
"""
@spec timeout_error() :: t()
def timeout_error do
%__MODULE__{
type: :timeout,
message: "Request timed out",
code: nil,
details: nil
}
end
@doc """
Create an invalid response error.
"""
@spec invalid_response(term()) :: t()
def invalid_response(reason) do
%__MODULE__{
type: :invalid_response,
message: "Invalid response: #{inspect(reason)}",
code: nil,
details: %{reason: reason}
}
end
@doc """
Create a missing credentials error.
"""
@spec missing_credentials() :: t()
def missing_credentials do
%__MODULE__{
type: :missing_credentials,
message: "API credentials not configured. Set APCA_API_KEY_ID and APCA_API_SECRET_KEY",
code: nil,
details: nil
}
end
# Private helpers
defp type_from_status(401), do: :unauthorized
defp type_from_status(403), do: :forbidden
defp type_from_status(404), do: :not_found
defp type_from_status(422), do: :unprocessable_entity
defp type_from_status(429), do: :rate_limited
defp type_from_status(status) when status >= 500, do: :server_error
defp type_from_status(_), do: :unknown
end
defimpl String.Chars, for: Alpa.Error do
def to_string(%Alpa.Error{type: type, message: message, code: code}) do
code_str = if code, do: " (#{code})", else: ""
"[#{type}]#{code_str} #{message}"
end
end