we-promise/sure · error · Provider::Brex::BrexError
fetch_failed
fetch_failed
Error message
Failed to fetch data from Brex API: HTTP #{response.code} What it means
Raised by Provider::Brex#handle_response for any status outside 200/400/401/403/404/429 — in practice Brex-side 5xx errors (500, 502, 503, 504) or unusual intermediary codes. The message embeds the exact HTTP code and the error carries http_status plus trace_id, so 5xx incidents can be correlated with Brex support.
Source
Thrown at app/models/provider/brex.rb:227
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 DateTime
start_date.to_time
when Date
start_date.to_time(:utc)View on GitHub (pinned to e69894adb9)
Solutions
- Check e.http_status on the raised BrexError — 5xx means retry after backoff; the request outcome may or may not have committed, but all Brex calls here are reads so retry is safe
- Check Brex status channels for an ongoing incident before burning retries
- Exponential backoff with a cap and let the next scheduled sync pick up if the outage lasts
- For repeated 5xx, collect trace_id values and report to Brex support
Example fix
# before client.get_accounts # after attempts = 0 begin client.get_accounts rescue Provider::Brex::BrexError => e raise unless e.http_status.to_i >= 500 && (attempts += 1) <= 3 sleep(2**attempts) retry end
Defensive patterns
Strategy: retry
Type guard
def brex_server_error?(error) error.is_a?(Provider::Brex::BrexError) && error.error_type == :fetch_failed && error.http_status.to_i >= 500 end
Try / catch
attempts = 0 begin client.get_accounts rescue Provider::Brex::BrexError => e raise unless e.error_type == :fetch_failed && e.http_status.to_i >= 500 && (attempts += 1) <= 3 sleep(2**attempts) retry end
Prevention
- Distinguish http_status 5xx (retry) from other unexpected codes (investigate) via e.http_status
- Keep trace_id from the error for incident reports to Brex
- Let the next scheduled sync absorb long outages instead of tight retry loops
- All Brex calls in this client are reads — retries are always side-effect-safe
When it happens
Trigger: Brex API incident returning 500/503 during a sync; gateway 502/504 when a paginated request takes too long upstream; maintenance windows answering 503.
Common situations: Provider-side outages noticed first as failed sync jobs; long backfill windows overlapping with Brex deploys.
Related errors
- fetch_failed
- server_error
- server_error
- SnapTrade server error (#{response.status}). Please try agai
- bad_request
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/d6dc0e33023714ff.
Report an issue: GitHub.