{"record":{"id":"47c86a1a3af068ec","repo":"we-promise/sure","slug":"no-chart-data-found-for-currency-pair-from-to","errorCode":null,"errorMessage":"No chart data found for currency pair #{from}/#{to}","messagePattern":"No chart data found for currency pair #(.+?)/#(.+?)","errorType":"exception","errorClass":"Provider::YahooFinance::Error","httpStatus":null,"severity":"error","filePath":"app/models/provider/yahoo_finance.rb","lineNumber":181,"sourceCode":"    end\n  end\n\n  def fetch_exchange_rates(from:, to:, start_date:, end_date:)\n    with_provider_response do\n      validate_date_range!(start_date, end_date)\n      # Return 1.0 rates if same currency\n      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)","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/yahoo_finance.rb#L163-L199","documentation":"Provider::YahooFinance::Error raised in fetch_exchange_rates when neither the direct currency pair chart (e.g. EURUSD=X) nor the inverse pair (USDEUR=X) returned any data for the range. The API responded but the chart payload was empty, so no rates can be built.","triggerScenarios":"Requesting a pair Yahoo Finance does not quote (exotic crosses like TRY/KRW), a date range entirely outside the pair's history, or a chart endpoint response whose chart.result is absent. Both direct and inverse fetches must fail for this to raise.","commonSituations":"Portfolio with currencies Yahoo doesn't cover as a direct pair; start_date before the pair's history begins; Yahoo silently changing chart response shape.","solutions":["Verify the pair exists on finance.yahoo.com (search 'EURTRY=X' style symbols) and use an explicit symbol if needed","Route through a cross via USD: compute rate as EURUSD × USDTRY when the direct pair is missing (fetch each leg separately)","Widen or shift the date range into the pair's available history","Fall back to a dedicated FX provider for uncovered pairs"],"exampleFix":"// before\nrates = provider.fetch_exchange_rates(from: \"TRY\", to: \"KRW\", start_date: s, end_date: e)\n\n// after\nbegin\n  rates = provider.fetch_exchange_rates(from: \"TRY\", to: \"KRW\", start_date: s, end_date: e)\nrescue Provider::YahooFinance::Error => e\n  raise unless e.message.include?(\"No chart data found\")\n  usd_base = provider.fetch_exchange_rates(from: \"TRY\", to: \"USD\", start_date: s, end_date: e).data.index_by(&:date)\n  rates = provider.fetch_exchange_rates(from: \"USD\", to: \"KRW\", start_date: s, end_date: e).data.map do |r|\n    Rate.new(date: r.date, from: \"TRY\", to: \"KRW\", rate: r.rate / usd_base[r.date].rate)\n  end\nend","handlingStrategy":"fallback","validationCode":"return Rate.new(date:, from:, to:, rate: 1.0) if from == to # same-currency pairs never need Yahoo","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.include?(\"No chart data found\")\n  # cross via USD: from->USD * USD->to\n  base = provider.fetch_exchange_rates(from: from, to: \"USD\", start_date:, end_date:).data.index_by(&:date)\n  provider.fetch_exchange_rates(from: \"USD\", to: to, start_date:, end_date:).data.filter_map do |r|\n    b = base[r.date]\n    b && Rate.new(date: r.date, from: from, to: to, rate: b.rate * r.rate)\n  end\nend","preventionTips":["Maintain a known-pairs list and route unsupported crosses through USD legs","Validate currency codes (ISO 4217) before calling Yahoo","Fall back to a dedicated FX API for exotic pairs"],"tags":["ruby","yahoo-finance","exchange-rate","currency-pair-unsupported","empty-response"],"backgroundTag":"currency-pair-not-supported","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}