{"record":{"id":"e3db9e9115fc745e","repo":"we-promise/sure","slug":"fetch-failed-e3db9e","errorCode":"fetch_failed","errorMessage":"Failed to fetch data: #{response.code} #{response.message} - #{response.body}","messagePattern":"Failed to fetch data: #(.+?) #(.+?) - #(.+?)","errorType":"exception","errorClass":"Provider::Lunchflow::LunchflowError","httpStatus":null,"severity":"error","filePath":"app/models/provider/lunchflow.rb","lineNumber":138,"sourceCode":"\n    def handle_response(response)\n      case response.code\n      when 200\n        JSON.parse(response.body, symbolize_names: true)\n      when 400\n        Rails.logger.error \"Lunch Flow API: Bad request - #{response.body}\"\n        raise LunchflowError.new(\"Bad request to Lunch Flow API: #{response.body}\", :bad_request)\n      when 401\n        raise LunchflowError.new(\"Invalid API key\", :unauthorized)\n      when 403\n        raise LunchflowError.new(\"Access forbidden - check your API key permissions\", :access_forbidden)\n      when 404\n        raise LunchflowError.new(\"Resource not found\", :not_found)\n      when 429\n        raise LunchflowError.new(\"Rate limit exceeded. Please try again later.\", :rate_limited)\n      else\n        Rails.logger.error \"Lunch Flow API: Unexpected response - Code: #{response.code}, Body: #{response.body}\"\n        raise LunchflowError.new(\"Failed to fetch data: #{response.code} #{response.message} - #{response.body}\", :fetch_failed)\n      end\n    end\n\n    class LunchflowError < StandardError\n      attr_reader :error_type\n\n      def initialize(message, error_type = :unknown)\n        super(message)\n        @error_type = error_type\n      end\n    end\nend\n","sourceCodeStart":120,"sourceCodeEnd":151,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/lunchflow.rb#L120-L151","documentation":"Fallback branch of Provider::Lunchflow#handle_response (app/models/provider/lunchflow.rb:136-138). Thrown as LunchflowError(:fetch_failed) for any status not in {200, 400, 401, 403, 404, 429}: server errors (500/502/503/504) during Lunchflow incidents, redirects (3xx — HTTParty does not follow redirects by default here, so an http:// base_url redirecting to https lands here), or unusual gateway codes. The message embeds the numeric code, HTTP message, and body, e.g. 'Failed to fetch data: 503 Service Unavailable - ...'.","triggerScenarios":"Lunchflow upstream outage or deploy returning 5xx; load balancer 502/504 when the origin times out; base_url using http:// so the server answers 301/302 which falls into this branch; custom base_url behind a gateway returning nonstandard codes.","commonSituations":"Provider maintenance windows caught by scheduled syncs; CDN/gateway mode returning 520-526 (Cloudflare); stale base_url scheme (http) after the provider forced TLS.","solutions":["Parse the status from the message ('Failed to fetch data: <code> ...') and the log line 'Unexpected response - Code: ...' to identify 5xx vs 3xx.","For 5xx, retry with backoff and check the Lunchflow status page; these are server-side and transient in most cases.","For 3xx codes, change the base_url to https:// so the request is not redirected.","Treat persistent 5xx on all endpoints as an outage: pause the sync and resume on recovery."],"exampleFix":"// before\nbase_url = 'http://lunchflow.example/api/v1'\nclient = Provider::Lunchflow.new(key, base_url: base_url)\n\n// after\nbase_url = 'https://lunchflow.example/api/v1'\nclient = Provider::Lunchflow.new(key, base_url: base_url)\nattempts = 0\nbegin\n  attempts += 1\n  client.get_accounts\nrescue Provider::Lunchflow::LunchflowError => e\n  raise unless e.error_type == :fetch_failed && e.message.match?(/\\AFailed to fetch data: 5/) && attempts < 3\n  sleep(2**attempts)\n  retry\nend","handlingStrategy":"retry","validationCode":"uri = URI.parse(client.base_url.to_s)\nraise ArgumentError, 'use https base_url to avoid 3xx fallback' unless uri.is_a?(URI::HTTPS)","typeGuard":"def server_error?(e)\n  e.is_a?(Provider::Lunchflow::LunchflowError) && e.error_type == :fetch_failed &&\n    e.message.match?(/\\AFailed to fetch data: 5\\d\\d/)\nend","tryCatchPattern":"attempts = 0\nbegin\n  attempts += 1\n  client.get_accounts\nrescue Provider::Lunchflow::LunchflowError => e\n  retryable = e.error_type == :fetch_failed && e.message.match?(/\\AFailed to fetch data: 5/)\n  raise unless retryable && attempts < 3\n  sleep(2**attempts)\n  retry\nend","preventionTips":["Always configure https:// base_urls so 3xx codes never reach this branch.","Pause syncs during announced provider maintenance windows.","Distinguish 5xx (retry) from 3xx (config bug) using the code in the message."],"tags":["lunchflow","http-5xx","server-error","redirect","httparty"],"backgroundTag":"server-error-5xx","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-22T04:17:13.399Z"}