Skip to main content

Error Hierarchy

All errors in the OpenAI Ruby SDK inherit from a common base class, making it easy to catch and handle exceptions.
OpenAI::Errors::Error                    # Base error class
├── OpenAI::Errors::ConversionError      # Type conversion failures
├── OpenAI::Errors::InvalidWebhookSignatureError
└── OpenAI::Errors::APIError             # Base API error
    ├── OpenAI::Errors::APIConnectionError
    │   └── OpenAI::Errors::APITimeoutError
    └── OpenAI::Errors::APIStatusError
        ├── OpenAI::Errors::BadRequestError          # 400
        ├── OpenAI::Errors::AuthenticationError      # 401
        ├── OpenAI::Errors::PermissionDeniedError    # 403
        ├── OpenAI::Errors::NotFoundError            # 404
        ├── OpenAI::Errors::ConflictError            # 409
        ├── OpenAI::Errors::UnprocessableEntityError # 422
        ├── OpenAI::Errors::RateLimitError           # 429
        └── OpenAI::Errors::InternalServerError      # 500+

Basic Error Handling

begin
  response = client.chat.completions.create(
    model: 'gpt-4',
    messages: [{role: 'user', content: 'Hello!'}]
  )
rescue OpenAI::Errors::Error => e
  puts "An error occurred: #{e.message}"
end

API Status Errors

HTTP status code errors include additional metadata about the failed request.

Error Attributes

status
integer
The HTTP status code (e.g., 400, 401, 500)
code
string | nil
The error code returned by the API
param
string | nil
The parameter that caused the error, if applicable
type
string | nil
The error type returned by the API
body
object | nil
The raw response body from the API
headers
hash | nil
The response headers
url
URI
The URL of the failed request

Example Usage

begin
  client.chat.completions.create(
    model: 'gpt-4',
    messages: [{role: 'user', content: 'Hi'}]
  )
rescue OpenAI::Errors::APIStatusError => e
  puts "Status: #{e.status}"
  puts "Code: #{e.code}"
  puts "Type: #{e.type}"
  puts "Param: #{e.param}"
  puts "URL: #{e.url}"
  puts "Body: #{e.body}"
end

Error Types Reference

Client Errors (4xx)

rescue OpenAI::Errors::BadRequestError => e
  # Invalid request parameters
  puts "Bad request: #{e.message}"
  puts "Invalid parameter: #{e.param}" if e.param
end

Server Errors (5xx)

rescue OpenAI::Errors::InternalServerError => e
  # Server error (500, 502, 503, 504, etc.)
  puts "Server error: #{e.message}"
  puts "Status: #{e.status}"
  # These are automatically retried by the SDK
end

Connection Errors

rescue OpenAI::Errors::APIConnectionError => e
  # Network connectivity issues
  puts "Connection error: #{e.message}"
  puts "Failed to connect to: #{e.url}"
  # Check network connectivity
end

Conversion Errors

rescue OpenAI::Errors::ConversionError => e
  # Failed to parse API response
  puts "Conversion error: #{e.message}"
  # Use bracket notation to access unparsed data
end

HTTP Status Code Table

Status CodeError ClassDescriptionRetryable
400BadRequestErrorInvalid request parametersNo
401AuthenticationErrorInvalid or missing API keyNo
403PermissionDeniedErrorInsufficient permissionsNo
404NotFoundErrorResource not foundNo
408APIStatusErrorRequest timeoutYes
409ConflictErrorResource conflictYes
422UnprocessableEntityErrorSemantic validation errorNo
429RateLimitErrorRate limit exceededYes
500+InternalServerErrorServer errorYes
Retryable errors are automatically retried by the SDK according to the configured retry policy. See Retries for details.

Comprehensive Error Handling

begin
  response = client.chat.completions.create(
    model: 'gpt-4',
    messages: [{role: 'user', content: 'Hello!'}]
  )
rescue OpenAI::Errors::AuthenticationError => e
  # Handle authentication failures
  logger.error "Invalid API key: #{e.message}"
  notify_admin(e)
rescue OpenAI::Errors::RateLimitError => e
  # Handle rate limiting
  retry_after = e.headers&.[]('retry-after')&.to_i || 60
  logger.warn "Rate limited, retrying after #{retry_after}s"
  sleep(retry_after)
  retry
rescue OpenAI::Errors::APITimeoutError => e
  # Handle timeouts
  logger.error "Request timed out: #{e.url}"
  # Maybe use streaming for long requests
rescue OpenAI::Errors::InternalServerError => e
  # Handle server errors
  logger.error "OpenAI server error (#{e.status}): #{e.message}"
  # SDK already retried, this is a persistent failure
rescue OpenAI::Errors::APIError => e
  # Catch-all for other API errors
  logger.error "API error: #{e.class} - #{e.message}"
rescue OpenAI::Errors::Error => e
  # Catch-all for SDK errors
  logger.error "SDK error: #{e.message}"
end

Error Message Extraction

The SDK automatically extracts error messages from the API response:
# lib/openai/errors.rb:219
message ||= OpenAI::Internal::Util.dig(body, :message) { {url: url.to_s, status: status, body: body} }
When debugging errors, inspect the body attribute for the full API response containing additional error details.

Build docs developers (and LLMs) love