Exception: SecApi::RateLimitError

Inherits:
TransientError show all
Defined in:
lib/sec_api/errors/rate_limit_error.rb

Overview

Raised when sec-api.io rate limit is exceeded (429 Too Many Requests).

Why TransientError? Rate limits reset after a time window (typically 60s). The request is valid - we just hit a temporary capacity limit. Worth waiting and retrying automatically rather than failing to the user. (FR5.4: auto-resume)

This is a transient error - the retry middleware will automatically retry the request after waiting for the rate limit to reset.

The error includes retry context when available from response headers:

  • #retry_after: Duration to wait (from Retry-After header)

  • #reset_at: Timestamp when rate limit resets (from X-RateLimit-Reset header)

Examples:

Handling rate limits

begin
  client.query.ticker("AAPL").search
rescue SecApi::RateLimitError => e
  # Retries exhausted - rate limit hit repeatedly
  logger.warn("Rate limit exceeded: #{e.message}")
  if e.retry_after
    logger.info("Server suggests waiting #{e.retry_after} seconds")
  end
  notify_ops_team(e)
end

Checking reset time

rescue SecApi::RateLimitError => e
  if e.reset_at
    wait_time = e.reset_at - Time.now
    sleep(wait_time) if wait_time.positive?
  end

Instance Attribute Summary collapse

Attributes inherited from Error

#request_id

Instance Method Summary collapse

Constructor Details

#initialize(message, retry_after: nil, reset_at: nil, request_id: nil) ⇒ RateLimitError

Creates a new RateLimitError with optional retry context.

Parameters:

  • message (String)

    Error message describing the rate limit

  • retry_after (Integer, nil) (defaults to: nil)

    Seconds to wait (from Retry-After header)

  • reset_at (Time, nil) (defaults to: nil)

    Timestamp when rate limit resets (from X-RateLimit-Reset header)

  • request_id (String, nil) (defaults to: nil)

    Request correlation ID for tracing



51
52
53
54
55
# File 'lib/sec_api/errors/rate_limit_error.rb', line 51

def initialize(message, retry_after: nil, reset_at: nil, request_id: nil)
  super(message, request_id: request_id)
  @retry_after = retry_after
  @reset_at = reset_at
end

Instance Attribute Details

#reset_atTime? (readonly)

Timestamp when the rate limit window resets (from X-RateLimit-Reset header).

Returns:

  • (Time, nil)

    Reset time, or nil if header was not present



43
44
45
# File 'lib/sec_api/errors/rate_limit_error.rb', line 43

def reset_at
  @reset_at
end

#retry_afterInteger? (readonly)

Duration in seconds to wait before retrying (from Retry-After header).

Returns:

  • (Integer, nil)

    Seconds to wait, or nil if header was not present



39
40
41
# File 'lib/sec_api/errors/rate_limit_error.rb', line 39

def retry_after
  @retry_after
end