LemonAi.Error (lemon_ai v0.1.0)

View Source

Error handling utilities for AI provider responses.

This module provides functions for:

  • Parsing HTTP error responses from various providers
  • Extracting rate limit information from response headers
  • Classifying errors for appropriate handling
  • Generating user-friendly error messages

Summary

Functions

Check if the error represents an authentication failure.

Check if the error represents a context length exceeded error.

Extract rate limit information from response headers.

Generate a user-friendly error message from an error term.

Format rate limit information for display.

Parse an HTTP error response into a structured error.

Check if the error represents a rate limit error.

Check if an error is retryable.

Suggest a retry delay based on the error.

Suggest a retry delay based on parsed error with rate limit info.

Types

error_category()

@type error_category() ::
  :rate_limit
  | :auth
  | :client
  | :context_length
  | :server
  | :transient
  | :unknown

parsed_error()

@type parsed_error() :: %{
  category: error_category(),
  status: non_neg_integer() | nil,
  message: String.t(),
  provider_message: String.t() | nil,
  rate_limit_info: rate_limit_info() | nil,
  retryable: boolean()
}

rate_limit_info()

@type rate_limit_info() :: %{
  limit: non_neg_integer() | nil,
  remaining: non_neg_integer() | nil,
  reset_at: DateTime.t() | nil,
  retry_after: non_neg_integer() | nil
}

Functions

auth_error?(arg1)

@spec auth_error?(term()) :: boolean()

Check if the error represents an authentication failure.

Examples

iex> LemonAi.Error.auth_error?({:http_error, 401, "Unauthorized"})
true

iex> LemonAi.Error.auth_error?({:http_error, 500, "Server Error"})
false

context_length_error?(error)

@spec context_length_error?(term()) :: boolean()

Check if the error represents a context length exceeded error.

Examples

iex> LemonAi.Error.context_length_error?({:http_error, 400, %{"error" => %{"code" => "context_length_exceeded"}}})
true

iex> LemonAi.Error.context_length_error?({:http_error, 429, "Rate limited"})
false

extract_rate_limit_info(headers)

@spec extract_rate_limit_info(map() | [{term(), term()}]) :: rate_limit_info()

Extract rate limit information from response headers.

Handles common rate limit header formats from OpenAI, Anthropic, and other providers.

Headers checked

  • x-ratelimit-limit-requests, x-ratelimit-limit-tokens - Total limit
  • x-ratelimit-remaining-requests, x-ratelimit-remaining-tokens - Remaining
  • x-ratelimit-reset-requests, x-ratelimit-reset-tokens - Reset timestamp
  • retry-after - Seconds until retry is allowed
  • retry-after-ms, x-ms-retry-after-ms - Milliseconds until retry is allowed

format_error(error)

@spec format_error(term()) :: String.t()

Generate a user-friendly error message from an error term.

format_rate_limit_info(arg1)

@spec format_rate_limit_info(rate_limit_info() | nil) :: String.t()

Format rate limit information for display.

Examples

iex> info = %{limit: 100, remaining: 50, reset_at: DateTime.utc_now()}
iex> LemonAi.Error.format_rate_limit_info(info)
"Rate limit: 50/100 remaining"

parse_http_error(status, body, headers \\ [])

@spec parse_http_error(non_neg_integer(), term(), map() | [{term(), term()}]) ::
  parsed_error()

Parse an HTTP error response into a structured error.

Examples

iex> LemonAi.Error.parse_http_error(429, %{"error" => %{"message" => "Rate limit exceeded"}}, headers)
%{category: :rate_limit, status: 429, message: "Rate limit exceeded", ...}

iex> LemonAi.Error.parse_http_error(500, "Internal Server Error", [])
%{category: :server, status: 500, message: "Internal server error", ...}

rate_limit_error?(arg1)

@spec rate_limit_error?(term()) :: boolean()

Check if the error represents a rate limit error.

Examples

iex> LemonAi.Error.rate_limit_error?({:http_error, 429, "Rate limited"})
true

iex> LemonAi.Error.rate_limit_error?(:rate_limited)
true

iex> LemonAi.Error.rate_limit_error?({:http_error, 500, "Server Error"})
false

retryable?(error)

@spec retryable?(term()) :: boolean()

Check if an error is retryable.

suggested_retry_delay(arg1)

@spec suggested_retry_delay(term()) :: non_neg_integer() | nil

Suggest a retry delay based on the error.

Returns the suggested delay in milliseconds, or nil if not applicable. Uses rate limit headers if available for more accurate retry timing.

suggested_retry_delay_from_error(arg1)

@spec suggested_retry_delay_from_error(parsed_error()) :: non_neg_integer() | nil

Suggest a retry delay based on parsed error with rate limit info.

This version considers rate limit headers for more accurate retry timing.

Examples

iex> error = %{rate_limit_info: %{retry_after: 30_000}}
iex> LemonAi.Error.suggested_retry_delay_from_error(error)
30_000

iex> error = %{status: 503, rate_limit_info: nil}
iex> LemonAi.Error.suggested_retry_delay_from_error(error)
5_000