{"record":{"id":"220b0f260ffe42e5","repo":"we-promise/sure","slug":"fetch-failed-220b0f","errorCode":"fetch_failed","errorMessage":"Failed to fetch accounts: #{response.code} #{response.message} - #{response.body}","messagePattern":"Failed to fetch accounts: #(.+?) #(.+?) - #(.+?)","errorType":"exception","errorClass":"Provider::Simplefin::SimplefinError","httpStatus":null,"severity":"error","filePath":"app/models/provider/simplefin.rb","lineNumber":103,"sourceCode":"    case response.code\n    when 200\n      JSON.parse(response.body, symbolize_names: true)\n    when 400\n      Rails.logger.error \"SimpleFin API: Bad request - #{response.body}\"\n      raise SimplefinError.new(\"Bad request to SimpleFin API: #{response.body}\", :bad_request)\n    when 403\n      raise SimplefinError.new(\"Access URL is no longer valid\", :access_forbidden)\n    when 402\n      raise SimplefinError.new(\"Payment required to access this account\", :payment_required)\n    when 429\n      Rails.logger.warn \"SimpleFin API: Rate limited - #{response.body}\"\n      raise SimplefinError.new(\"SimpleFin rate limit exceeded. Please try again later.\", :rate_limited)\n    when 500..599\n      Rails.logger.error \"SimpleFin API: Server error - Code: #{response.code}, Body: #{response.body}\"\n      raise SimplefinError.new(\"SimpleFin server error (#{response.code}). Please try again later.\", :server_error)\n    else\n      Rails.logger.error \"SimpleFin API: Unexpected response - Code: #{response.code}, Body: #{response.body}\"\n      raise SimplefinError.new(\"Failed to fetch accounts: #{response.code} #{response.message} - #{response.body}\", :fetch_failed)\n    end\n  end\n\n  def get_info(base_url)\n    # Use self.class.get to inherit class-level SSL and timeout defaults\n    response = self.class.get(\"#{base_url}/info\")\n\n    case response.code\n    when 200\n      response.body.strip.split(\"\\n\")\n    else\n      raise SimplefinError.new(\"Failed to get server info: #{response.code} #{response.message}\", :info_failed)\n    end\n  end\n\n  class SimplefinError < StandardError\n    attr_reader :error_type\n","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/simplefin.rb#L85-L121","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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","Verify the stored access URL with an exact curl reproduction of the request","Check the Rails log line 'SimpleFin API: Unexpected response - Code: ... Body: ...' for the body, which often names the real problem","If SimpleFIN changed its endpoint shape, update this case statement to handle the new status explicitly"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  simplefin.get_accounts\nrescue Provider::Simplefin::SimplefinError => e\n  case e.error_type\n  when :fetch_failed then flag_access_url_for_relink(e.message) # unexpected status: usually stale URL\n  else raise\n  end\nend","preventionTips":["Validate the stored access URL format (https, host present) before first use","Treat any redirect-bearing status as 'relink needed' rather than a code bug","Log error_type alongside the message so unhandled statuses are countable"],"tags":["simplefin","http-status","access-url","redirect","provider-api"],"backgroundTag":"unexpected-http-status","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}