we-promise/sure · error · Provider::Simplefin::SimplefinError

fetch_failed

fetch_failed

Error message

Failed to fetch accounts: #{response.code} #{response.message} - #{response.body}

What it means

Raised by Provider::Simplefin's response handler for any HTTP status not explicitly handled (everything other than 200, 400, 402, 403, 429, 500-599). It is the catch-all 'unexpected response' branch of the accounts fetch; the message embeds the raw status code, HTTP message, and body so the actual status can be diagnosed. The error_type is :fetch_failed.

Source

Thrown at app/models/provider/simplefin.rb:103

    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)
    end
  end

  class SimplefinError < StandardError
    attr_reader :error_type

View on GitHub (pinned to e69894adb9)

Solutions

  1. Read the code in the message: 301/302 means the access URL moved - re-generate/re-link the access URL in SimpleFIN and update the stored credential
  2. Verify the stored access URL with an exact curl reproduction of the request
  3. Check the Rails log line 'SimpleFin API: Unexpected response - Code: ... Body: ...' for the body, which often names the real problem
  4. If SimpleFIN changed its endpoint shape, update this case statement to handle the new status explicitly
Defensive patterns

Strategy: try-catch

Try / catch

begin
  simplefin.get_accounts
rescue Provider::Simplefin::SimplefinError => e
  case e.error_type
  when :fetch_failed then flag_access_url_for_relink(e.message) # unexpected status: usually stale URL
  else raise
  end
end

Prevention

When it happens

Trigger: The access URL returns an unhandled status: 301/302 redirect (HTTParty does not follow redirects by default, so a moved/rotated access URL lands here), 401, 404, 405, or 410. Any surprising non-listed code from the SimpleFIN endpoint hits this branch.

Common situations: SimpleFIN rotated or invalidated the access URL and now redirects; the stored access URL was truncated or copy-pasted wrongly; the endpoint scheme changed after a SimpleFIN product update; a 404 from a malformed URL.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/220b0f260ffe42e5. Report an issue: GitHub.