{"record":{"id":"07c2631596e0a6a2","repo":"we-promise/sure","slug":"invalid-response-format-e-message","errorCode":null,"errorMessage":"Invalid response format: #{e.message}","messagePattern":"Invalid response format: #(.+?)","errorType":"exception","errorClass":"Provider::YahooFinance::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/yahoo_finance.rb","lineNumber":188,"sourceCode":"      if from == to\n        generate_same_currency_rates(from, to, start_date, end_date)\n      else\n        cache_key = \"exchange_rates_#{from}_#{to}_#{start_date}_#{end_date}\"\n        if cached_result = get_cached_result(cache_key)\n          cached_result\n        else\n          # Try both direct and inverse currency pairs\n          rates = fetch_currency_pair_data(from, to, start_date, end_date) ||\n                  fetch_inverse_currency_pair_data(from, to, start_date, end_date)\n\n          raise Error, \"No chart data found for currency pair #{from}/#{to}\" unless rates&.any?\n\n          cache_result(cache_key, rates)\n          rates\n        end\n      end\n    rescue JSON::ParserError => e\n      raise Error, \"Invalid response format: #{e.message}\"\n    end\n  end\n\n  # ================================\n  #           Securities\n  # ================================\n\n  def search_securities(symbol, country_code: nil, exchange_operating_mic: nil)\n    with_provider_response do\n      cache_key = \"search_#{symbol}_#{country_code}_#{exchange_operating_mic}\"\n      if cached_result = get_cached_result(cache_key)\n        cached_result\n      else\n        throttle_request\n        response = client.get(\"#{base_url}/v1/finance/search\") do |req|\n          req.params[\"q\"] = symbol.strip.upcase\n          req.params[\"quotesCount\"] = 25\n        end","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/yahoo_finance.rb#L170-L206","documentation":"Provider::YahooFinance::Error raised in fetch_exchange_rates when JSON.parse fails on the chart endpoint's response body. Yahoo returned something that is not valid JSON — typically an HTML error/bot-check page, an empty body, or a truncated response — so parsing raised JSON::ParserError, re-raised as a typed provider error.","triggerScenarios":"Yahoo Finance (an unofficial, unauthenticated API) returning an HTML consent/captcha page, a 429 HTML error page, or an empty body on the chart endpoint; a proxy or corporate firewall mangling the response; CDN edge returning compressed/HTML content the client misreads.","commonSituations":"Yahoo throttling unauthenticated scrapers; IP blocked or geo-consent interstitials (EU cookie walls); datacenter egress IPs flagged as bots; response shape/encoding changes after Yahoo deploys updates.","solutions":["Log or inspect response.body when this fires — HTML content confirms a block/consent page rather than a parse bug","Back off and retry later; check provider.health_status which tracks Yahoo's availability","Route requests through a different egress IP or add a browser-like User-Agent if running from a datacenter","Fall back to another rates provider; Yahoo's unofficial endpoints change without notice"],"exampleFix":"// before\nrates = provider.fetch_exchange_rates(from: \"EUR\", to: \"USD\", start_date: s, end_date: e)\n\n// after\nbegin\n  rates = provider.fetch_exchange_rates(from: \"EUR\", to: \"USD\", start_date: s, end_date: e)\nrescue Provider::YahooFinance::Error => e\n  raise unless e.message.start_with?(\"Invalid response format\")\n  rates = fallback_provider.fetch_exchange_rates(from: \"EUR\", to: \"USD\", start_date: s, end_date: e)\nend","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"begin\n  provider.fetch_exchange_rates(from:, to:, start_date:, end_date:)\nrescue Provider::YahooFinance::Error => e\n  raise unless e.message.start_with?(\"Invalid response format\")\n  # Yahoo served non-JSON (block page) — back off, then fall back\n  retry if (attempts += 1) < 2\n  fallback_provider.fetch_exchange_rates(from:, to:, start_date:, end_date:)\nend","preventionTips":["Respect health_status: when Yahoo reads rate_limited/unavailable, defer work","Log raw bodies on parse failure to distinguish bot-blocks from transient truncation","Never treat Yahoo's unofficial endpoints as a sole source — keep a fallback provider"],"tags":["ruby","yahoo-finance","json-parse-error","html-response","scraping"],"backgroundTag":"invalid-json-response","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}