we-promise/sure · warning · Provider::Brex::BrexError
rate_limited
rate_limited
Error message
Brex rate limit exceeded. Please try again later.
What it means
Raised by Provider::Brex#handle_response on HTTP 429: Brex's rate limit was exceeded and the request was not processed. It is transient by design — the same call succeeds after waiting — and get_paginated's tight loop (limit 1000, up to MAX_PAGES 25 pages per resource) can trip it when syncing many accounts. http_status 429 and trace_id are attached.
Source
Thrown at app/models/provider/brex.rb:224
case response.code
when 200
parse_json(response.body)
when 400
Rails.logger.error "Brex API: bad request for #{path} trace_id=#{trace_id}"
raise BrexError.new("Bad request to Brex API", :bad_request, http_status: 400, trace_id: trace_id)
when 401
Rails.logger.warn "Brex API: unauthorized for #{path} trace_id=#{trace_id}"
raise BrexError.new("Invalid Brex API token or account permissions", :unauthorized, http_status: 401, trace_id: trace_id)
when 403
Rails.logger.warn "Brex API: access forbidden for #{path} trace_id=#{trace_id}"
raise BrexError.new("Access forbidden - check Brex API token scopes", :access_forbidden, http_status: 403, trace_id: trace_id)
when 404
Rails.logger.warn "Brex API: resource not found for #{path} trace_id=#{trace_id}"
raise BrexError.new("Brex resource not found", :not_found, http_status: 404, trace_id: trace_id)
when 429
Rails.logger.warn "Brex API: rate limited for #{path} trace_id=#{trace_id}"
raise BrexError.new("Brex rate limit exceeded. Please try again later.", :rate_limited, http_status: 429, trace_id: trace_id)
else
Rails.logger.error "Brex API: unexpected response code=#{response.code} path=#{path} trace_id=#{trace_id}"
raise BrexError.new("Failed to fetch data from Brex API: HTTP #{response.code}", :fetch_failed, http_status: response.code, trace_id: trace_id)
end
end
def parse_json(body)
return {} if body.blank?
JSON.parse(body, symbolize_names: true)
end
def rfc3339_start_date(start_date)
time =
case start_date
when Time
start_date
when DateTimeView on GitHub (pinned to e69894adb9)
Solutions
- Retry the failed call after an exponential backoff (start ~seconds, not milliseconds) — the request was not processed, so retry is safe
- Serialize or stagger Brex sync jobs per token so concurrent paginated loops don't stack
- Lengthen the sync interval or reduce the number of accounts synced per run
- If persistent, check the Brex dashboard for the token's quota tier and request a raise
Example fix
# before client.get_cash_transactions(account_id, start_date: from) # after attempts = 0 begin client.get_cash_transactions(account_id, start_date: from) rescue Provider::Brex::BrexError => e raise unless e.error_type == :rate_limited && (attempts += 1) <= 5 sleep((2**attempts) + rand(2)) retry end
Defensive patterns
Strategy: retry
Validate before calling
# Cheap client-side throttle before a sync burst class BrexRateLimiter def initialize(min_interval: 0.5) = (@min_interval = min_interval) def throttle! = (now = Process.clock_gettime(Process::CLOCK_MONOTONIC); sleep(@min_interval - (now - @last)) if @last && (now - @last) < @min_interval; @last = Process.clock_gettime(Process::CLOCK_MONOTONIC)) end
Type guard
def brex_rate_limited?(error) error.is_a?(Provider::Brex::BrexError) && error.error_type == :rate_limited end
Try / catch
attempts = 0 begin client.get_accounts rescue Provider::Brex::BrexError => e raise unless e.error_type == :rate_limited && (attempts += 1) <= 5 sleep((2**attempts) + rand(2)) # exponential + jitter retry end
Prevention
- Serialize Brex sync jobs per token; stagger schedules with jitter
- Space paginated requests with a small client-side interval
- Cap backfill windows so get_paginated does fewer pages per run
- Alert only when 429s persist after backoff, not on single occurrences
When it happens
Trigger: Several get_paginated loops running concurrently for the same token; frequent scheduled syncs (e.g. every minute) stacking up; a burst of page requests within one large transaction backfill exceeding the per-minute quota.
Common situations: Parallel background jobs syncing multiple Brex connections simultaneously, cron schedules drifting together, initial historical backfills that page heavily.
Related errors
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/f90fcca6c76c4aa1.
Report an issue: GitHub.