we-promise/sure · error · Provider::YahooFinance::Error

No chart data found for currency pair #{from}/#{to}

Error message

No chart data found for currency pair #{from}/#{to}

What it means

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.

Source

Thrown at app/models/provider/yahoo_finance.rb:181

    end
  end

  def fetch_exchange_rates(from:, to:, start_date:, end_date:)
    with_provider_response do
      validate_date_range!(start_date, end_date)
      # Return 1.0 rates if same currency
      if from == to
        generate_same_currency_rates(from, to, start_date, end_date)
      else
        cache_key = "exchange_rates_#{from}_#{to}_#{start_date}_#{end_date}"
        if cached_result = get_cached_result(cache_key)
          cached_result
        else
          # Try both direct and inverse currency pairs
          rates = fetch_currency_pair_data(from, to, start_date, end_date) ||
                  fetch_inverse_currency_pair_data(from, to, start_date, end_date)

          raise Error, "No chart data found for currency pair #{from}/#{to}" unless rates&.any?

          cache_result(cache_key, rates)
          rates
        end
      end
    rescue JSON::ParserError => e
      raise Error, "Invalid response format: #{e.message}"
    end
  end

  # ================================
  #           Securities
  # ================================

  def search_securities(symbol, country_code: nil, exchange_operating_mic: nil)
    with_provider_response do
      cache_key = "search_#{symbol}_#{country_code}_#{exchange_operating_mic}"
      if cached_result = get_cached_result(cache_key)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Verify the pair exists on finance.yahoo.com (search 'EURTRY=X' style symbols) and use an explicit symbol if needed
  2. Route through a cross via USD: compute rate as EURUSD × USDTRY when the direct pair is missing (fetch each leg separately)
  3. Widen or shift the date range into the pair's available history
  4. Fall back to a dedicated FX provider for uncovered pairs

Example fix

// before
rates = provider.fetch_exchange_rates(from: "TRY", to: "KRW", start_date: s, end_date: e)

// after
begin
  rates = provider.fetch_exchange_rates(from: "TRY", to: "KRW", start_date: s, end_date: e)
rescue Provider::YahooFinance::Error => e
  raise unless e.message.include?("No chart data found")
  usd_base = provider.fetch_exchange_rates(from: "TRY", to: "USD", start_date: s, end_date: e).data.index_by(&:date)
  rates = provider.fetch_exchange_rates(from: "USD", to: "KRW", start_date: s, end_date: e).data.map do |r|
    Rate.new(date: r.date, from: "TRY", to: "KRW", rate: r.rate / usd_base[r.date].rate)
  end
end
Defensive patterns

Strategy: fallback

Validate before calling

return Rate.new(date:, from:, to:, rate: 1.0) if from == to # same-currency pairs never need Yahoo

Try / catch

begin
  provider.fetch_exchange_rates(from:, to:, start_date:, end_date:)
rescue Provider::YahooFinance::Error => e
  raise unless e.message.include?("No chart data found")
  # cross via USD: from->USD * USD->to
  base = provider.fetch_exchange_rates(from: from, to: "USD", start_date:, end_date:).data.index_by(&:date)
  provider.fetch_exchange_rates(from: "USD", to: to, start_date:, end_date:).data.filter_map do |r|
    b = base[r.date]
    b && Rate.new(date: r.date, from: from, to: to, rate: b.rate * r.rate)
  end
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21). Data as JSON: /api/errors/47c86a1a3af068ec. Report an issue: GitHub.