{"record":{"id":"70f995af13c62280","repo":"we-promise/sure","slug":"snaptrade-api-error-operation-http-respons","errorCode":null,"errorMessage":"SnapTrade API error (#{operation}): HTTP #{response.status}","messagePattern":"SnapTrade API error \\(#(.+?)\\): HTTP #(.+?)","errorType":"exception","errorClass":"Provider::Snaptrade::ApiError","httpStatus":null,"severity":"error","filePath":"app/models/provider/snaptrade.rb","lineNumber":395,"sourceCode":"          JSON.parse(response.body)\n        rescue JSON::ParserError\n          raise ApiError.new(\"SnapTrade API error (#{operation}): invalid JSON response\",\n                             status_code: response.status, response_body: response.body)\n        end\n      else\n        Rails.logger.error(\"SnapTrade API error (#{operation}): #{response.status}\")\n        case response.status\n        when 401, 403\n          mark_requires_update!\n          raise AuthenticationError, \"Authentication failed (#{operation}): HTTP #{response.status}\"\n        when 429\n          raise ApiError.new(\"Rate limit exceeded. Please try again later.\",\n                             status_code: response.status, response_body: response.body)\n        when 500..599\n          raise ApiError.new(\"SnapTrade server error (#{response.status}). Please try again later.\",\n                             status_code: response.status, response_body: response.body)\n        else\n          raise ApiError.new(\"SnapTrade API error (#{operation}): HTTP #{response.status}\",\n                             status_code: response.status, response_body: response.body)\n        end\n      end\n    end\n\n    def api_connection\n      @api_connection ||= Faraday.new do |faraday|\n        faraday.options.timeout = 30\n        faraday.options.open_timeout = 10\n      end\n    end\n\n    def with_retries(operation_name, max_retries: MAX_RETRIES)\n      retries = 0\n\n      begin\n        yield\n      rescue Faraday::TimeoutError, Faraday::ConnectionFailed, Errno::ECONNRESET, Errno::ETIMEDOUT => e","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/snaptrade.rb#L377-L413","documentation":"The fallback branch of Provider::Snaptrade.handle_response: any HTTP status other than 2xx, 401/403, 429, and 500-599 raises this generic ApiError with the operation name and status. The error object exposes status_code and response_body for diagnosis; 400-class and 404-class responses land here.","triggerScenarios":"Calling a SnapTrade endpoint with a bad parameter (400), a deleted/unknown account_id (404), a removed endpoint after an API version bump (404/410), or any status the case statement does not special-case.","commonSituations":"Stored SnapTrade account reference stale after the user re-linked the connection (old account_id now 404s); request parameter changes after upgrading the snaptrade gem/API version; malformed query params (bad date format in startDate).","solutions":["Inspect err.status_code and err.response_body - the body usually names the invalid parameter or missing resource","404: re-fetch the account list for the connection - the account may have been closed or re-keyed on re-link","400: validate request params (date formats, account_id shape) against the current SnapTrade API docs for that operation","After a SnapTrade API version change, audit each operation name in the message against the new endpoint signatures"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"def valid_snaptrade_account_id?(id)\n  id.is_a?(String) && id.match?(/\\A[0-9a-f-]{36}\\z/i) # adjust to SnapTrade's id shape\nend","typeGuard":null,"tryCatchPattern":"begin\n  snaptrade.get_positions(account_id: id)\nrescue Provider::Snaptrade::ApiError => e\n  if [400, 404, 410].include?(e.status_code)\n    refresh_account_list!(e.response_body) # stale ids: re-sync from source of truth\n  else\n    raise\n  end\nend","preventionTips":["Always branch on e.status_code / e.response_body rather than the formatted message","Re-fetch the account list when a stored account_id starts 404ing (user re-linked)","Validate request params (ids, dates) against current SnapTrade docs after gem/API upgrades"],"tags":["snaptrade","http-400","http-404","api-error","faraday"],"backgroundTag":"unexpected-http-status","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}