{"record":{"id":"d6dc0e33023714ff","repo":"we-promise/sure","slug":"fetch-failed","errorCode":"fetch_failed","errorMessage":"Failed to fetch data from Brex API: HTTP #{response.code}","messagePattern":"Failed to fetch data from Brex API: HTTP #(.+?)","errorType":"http","errorClass":"Provider::Brex::BrexError","httpStatus":null,"severity":"error","filePath":"app/models/provider/brex.rb","lineNumber":227,"sourceCode":"        parse_json(response.body)\n      when 400\n        Rails.logger.error \"Brex API: bad request for #{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Bad request to Brex API\", :bad_request, http_status: 400, trace_id: trace_id)\n      when 401\n        Rails.logger.warn \"Brex API: unauthorized for #{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Invalid Brex API token or account permissions\", :unauthorized, http_status: 401, trace_id: trace_id)\n      when 403\n        Rails.logger.warn \"Brex API: access forbidden for #{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Access forbidden - check Brex API token scopes\", :access_forbidden, http_status: 403, trace_id: trace_id)\n      when 404\n        Rails.logger.warn \"Brex API: resource not found for #{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Brex resource not found\", :not_found, http_status: 404, trace_id: trace_id)\n      when 429\n        Rails.logger.warn \"Brex API: rate limited for #{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Brex rate limit exceeded. Please try again later.\", :rate_limited, http_status: 429, trace_id: trace_id)\n      else\n        Rails.logger.error \"Brex API: unexpected response code=#{response.code} path=#{path} trace_id=#{trace_id}\"\n        raise BrexError.new(\"Failed to fetch data from Brex API: HTTP #{response.code}\", :fetch_failed, http_status: response.code, trace_id: trace_id)\n      end\n    end\n\n    def parse_json(body)\n      return {} if body.blank?\n\n      JSON.parse(body, symbolize_names: true)\n    end\n\n    def rfc3339_start_date(start_date)\n      time =\n        case start_date\n        when Time\n          start_date\n        when DateTime\n          start_date.to_time\n        when Date\n          start_date.to_time(:utc)","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/brex.rb#L209-L245","documentation":"Raised by Provider::Brex#handle_response for any status outside 200/400/401/403/404/429 — in practice Brex-side 5xx errors (500, 502, 503, 504) or unusual intermediary codes. The message embeds the exact HTTP code and the error carries http_status plus trace_id, so 5xx incidents can be correlated with Brex support.","triggerScenarios":"Brex API incident returning 500/503 during a sync; gateway 502/504 when a paginated request takes too long upstream; maintenance windows answering 503.","commonSituations":"Provider-side outages noticed first as failed sync jobs; long backfill windows overlapping with Brex deploys.","solutions":["Check e.http_status on the raised BrexError — 5xx means retry after backoff; the request outcome may or may not have committed, but all Brex calls here are reads so retry is safe","Check Brex status channels for an ongoing incident before burning retries","Exponential backoff with a cap and let the next scheduled sync pick up if the outage lasts","For repeated 5xx, collect trace_id values and report to Brex support"],"exampleFix":"# before\nclient.get_accounts\n\n# after\nattempts = 0\nbegin\n  client.get_accounts\nrescue Provider::Brex::BrexError => e\n  raise unless e.http_status.to_i >= 500 && (attempts += 1) <= 3\n  sleep(2**attempts)\n  retry\nend","handlingStrategy":"retry","validationCode":null,"typeGuard":"def brex_server_error?(error)\n  error.is_a?(Provider::Brex::BrexError) && error.error_type == :fetch_failed && error.http_status.to_i >= 500\nend","tryCatchPattern":"attempts = 0\nbegin\n  client.get_accounts\nrescue Provider::Brex::BrexError => e\n  raise unless e.error_type == :fetch_failed && e.http_status.to_i >= 500 && (attempts += 1) <= 3\n  sleep(2**attempts)\n  retry\nend","preventionTips":["Distinguish http_status 5xx (retry) from other unexpected codes (investigate) via e.http_status","Keep trace_id from the error for incident reports to Brex","Let the next scheduled sync absorb long outages instead of tight retry loops","All Brex calls in this client are reads — retries are always side-effect-safe"],"tags":["brex","http-5xx","outage","upstream"],"backgroundTag":"http-5xx-server-error","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}