we-promise/sure · critical · Provider::Simplefin::SimplefinError
access_forbidden
access_forbidden
Error message
Access URL is no longer valid
What it means
Raised by Provider::Simplefin#get_accounts when the accounts endpoint returns 403, with error_type :access_forbidden. The claimed access URL embeds HTTP Basic Auth credentials; a 403 means those credentials were revoked server-side. This is permanent for that URL — the user must issue a new setup token and re-claim.
Source
Thrown at app/models/provider/simplefin.rb:92
accounts_url = "#{access_url}/accounts"
accounts_url += "?#{URI.encode_www_form(query_params)}" unless query_params.empty?
# The access URL already contains HTTP Basic Auth credentials
# 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")
View on GitHub (pinned to e69894adb9)
Solutions
- Have the user generate a new setup token and run the claim flow again
- Clear the stored access URL immediately so jobs stop hitting the revoked credentials
- Mark the SimpleFin connection as needing re-link and notify the user
- Distinguish this from a one-time claim failure: here the URL worked before and has since been revoked
Example fix
# before def sync(account) data = client.get_accounts(account.access_url) end # after def sync(account) data = client.get_accounts(account.access_url) rescue Provider::Simplefin::SimplefinError => e raise unless e.error_type == :access_forbidden account.update!(access_url: nil, needs_relink: true) UserMailer.simplefin_relink(account.user).deliver_later end
Defensive patterns
Strategy: try-catch
Validate before calling
def simplefin_url_alive?(client, base_url) client.get_info(base_url) true rescue Provider::Simplefin::SimplefinError false end
Type guard
def simplefin_access_revoked?(error) error.is_a?(Provider::Simplefin::SimplefinError) && error.error_type == :access_forbidden end
Try / catch
begin client.get_accounts(account.access_url) rescue Provider::Simplefin::SimplefinError => e raise unless e.error_type == :access_forbidden account.update!(access_url: nil, status: "needs_relink") UserMailer.simplefin_relink(account.user).deliver_later end
Prevention
- Null out stored access URLs the moment a 403 is seen — retrying a revoked URL never works
- Build the relink (new setup token -> claim) flow before launch; 403s are inevitable over time
- Distinguish :access_forbidden (revoked) from :token_compromised (claim-time) in support copy
When it happens
Trigger: User clicked 'reset/revoke access' at their SimpleFin bridge; bridge rotated credentials; the access URL was claimed from a different account context and got invalidated.
Common situations: Bank re-link flows where the old access URL persists locally; user troubleshooting by resetting the SimpleFin connection; bridge migrations invalidating old URLs.
Related errors
- token_compromised
- fetch_failed
- Please provide a name and a complete US address (street, cit
- access_forbidden
- access_forbidden
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/a5d1223971c4b9e8.
Report an issue: GitHub.