we-promise/sure · warning · Provider::Simplefin::SimplefinError
rate_limited
rate_limited
Error message
SimpleFin rate limit exceeded. Please try again later.
What it means
Raised by Provider::Simplefin#get_accounts on HTTP 429, error_type :rate_limited. Important difference from the Redbark client: SimpleFin's with_retries only retries network exceptions (RETRYABLE_ERRORS) — the status-code case statement runs outside the retry block, so a 429 is NOT retried internally and reaches the caller on the first occurrence.
Source
Thrown at app/models/provider/simplefin.rb:97
# Use retry logic with exponential backoff for transient network failures
# Use self.class.get to inherit class-level SSL and timeout defaults
response = with_retries("GET /accounts") do
self.class.get(accounts_url)
end
case response.code
when 200
JSON.parse(response.body, symbolize_names: true)
when 400
Rails.logger.error "SimpleFin API: Bad request - #{response.body}"
raise SimplefinError.new("Bad request to SimpleFin API: #{response.body}", :bad_request)
when 403
raise SimplefinError.new("Access URL is no longer valid", :access_forbidden)
when 402
raise SimplefinError.new("Payment required to access this account", :payment_required)
when 429
Rails.logger.warn "SimpleFin API: Rate limited - #{response.body}"
raise SimplefinError.new("SimpleFin rate limit exceeded. Please try again later.", :rate_limited)
when 500..599
Rails.logger.error "SimpleFin API: Server error - Code: #{response.code}, Body: #{response.body}"
raise SimplefinError.new("SimpleFin server error (#{response.code}). Please try again later.", :server_error)
else
Rails.logger.error "SimpleFin API: Unexpected response - Code: #{response.code}, Body: #{response.body}"
raise SimplefinError.new("Failed to fetch accounts: #{response.code} #{response.message} - #{response.body}", :fetch_failed)
end
end
def get_info(base_url)
# Use self.class.get to inherit class-level SSL and timeout defaults
response = self.class.get("#{base_url}/info")
case response.code
when 200
response.body.strip.split("\n")
else
raise SimplefinError.new("Failed to get server info: #{response.code} #{response.message}", :info_failed)View on GitHub (pinned to e69894adb9)
Solutions
- Implement caller-side backoff on :rate_limited — the library will not retry it for you
- Increase the interval between scheduled SimpleFin syncs
- Serialize syncs per bridge instead of hitting several accounts in parallel
- Check the response body in logs for the bridge's stated limit/window
Example fix
# before client.get_accounts(access_url) # no retry on 429 # after attempt = 0 begin client.get_accounts(access_url) rescue Provider::Simplefin::SimplefinError => e raise unless e.error_type == :rate_limited raise if (attempt += 1) >= 3 sleep(30 * attempt + rand(10)) retry end
Defensive patterns
Strategy: retry
Type guard
def simplefin_rate_limited?(error) error.is_a?(Provider::Simplefin::SimplefinError) && error.error_type == :rate_limited end
Try / catch
attempt = 0 begin client.get_accounts(access_url) rescue Provider::Simplefin::SimplefinError => e raise unless e.error_type == :rate_limited raise if (attempt += 1) >= 3 sleep((2**attempt) + rand(2)) # caller must retry: the client does not retry 429 retry end
Prevention
- Remember SimpleFin's client does NOT retry 429s (unlike Redbark) — always add caller-side backoff
- Serialize per-bridge syncs and space schedules minutes apart
- Log the bridge's 429 body; it often states the window you must wait
When it happens
Trigger: Polling the same access URL too frequently, several accounts on one bridge syncing concurrently, or scheduled jobs bunching up against the bridge's rate limit.
Common situations: Autosync interval shorter than the bridge tolerates; multiple app instances (staging+prod) sharing one bridge; retry loops at the caller level amplifying request volume.
Related errors
- Rate limit exceeded. Please try again later.
- rate_limited
- Rate limit exceeded
- Please provide a name and a complete US address (street, cit
- rate_limited
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/fc5cb5f9e381ad0a.
Report an issue: GitHub.