we-promise/sure · error · Provider::YahooFinance::Error
No exchange rate found for #{from}/#{to} on or before #{date
Error message
No exchange rate found for #{from}/#{to} on or before #{date} What it means
Provider::YahooFinance::Error raised in fetch_exchange_rate when the fetched 10-day window returned rates but none match the target date and none are on or before it. Every returned bar is later than the requested date, so no 'exact or closest previous' rate exists.
Source
Thrown at app/models/provider/yahoo_finance.rb:156
rates_response = fetch_exchange_rates(
from: from,
to: to,
start_date: start_date,
end_date: end_date
)
raise Error, "Failed to fetch exchange rates: #{rates_response.error.message}" unless rates_response.success?
rates = rates_response.data
if rates.length == 1
rates.first
else
# Find the exact date or the closest previous date
target_rate = rates.find { |r| r.date == date } ||
rates.select { |r| r.date <= date }.max_by(&:date)
raise Error, "No exchange rate found for #{from}/#{to} on or before #{date}" unless target_rate
cache_result(cache_key, target_rate)
target_rate
end
end
end
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)View on GitHub (pinned to e69894adb9)
Solutions
- Confirm the requested date is in the past and within Yahoo's history for the pair — very old dates may simply be unavailable
- For recent-date failures, retry with end_date = date + 1.day or use fetch_exchange_rates directly and pick the latest bar manually
- Fall back to another FX provider for dates Yahoo can't serve
- Normalize dates to the exchange's timezone before comparing
Example fix
// before
rate = provider.fetch_exchange_rate(from: "EUR", to: "USD", date: Date.new(2010, 1, 4))
// after
begin
rate = provider.fetch_exchange_rate(from: "EUR", to: "USD", date: date)
rescue Provider::YahooFinance::Error => e
raise unless e.message.include?("No exchange rate found")
resp = provider.fetch_exchange_rates(from: "EUR", to: "USD", start_date: date - 30.days, end_date: date + 1.day)
rate = resp.data.select { |r| r.date <= date }.max_by(&:date) or raise e
end Defensive patterns
Strategy: fallback
Validate before calling
raise ArgumentError, "date must be in the past" if date > Date.current
Try / catch
begin
provider.fetch_exchange_rate(from:, to:, date:)
rescue Provider::YahooFinance::Error => e
raise unless e.message.include?("No exchange rate found")
resp = provider.fetch_exchange_rates(from:, to:, start_date: date - 30.days, end_date: date + 1.day)
resp.data.select { |r| r.date <= date }.max_by(&:date) || fallback_provider.fetch_exchange_rate(from:, to:, date:)
end Prevention
- Guard against future dates before requesting
- For old transactions, try a wider window or a dedicated historical-FX provider
- Handle timezone-sensitive date comparisons explicitly (normalize to UTC/exchange tz)
When it happens
Trigger: Requesting a rate for a date older than Yahoo's available history for the pair (e.g. a 15-year-old transaction on a newly listed currency), a future date, or a pair whose 10-day lookback window starts after the target date. Timezone shifts can also make returned dates parse as after the requested date.
Common situations: Importing very old transactions whose FX history Yahoo no longer serves; requesting today/forward dates when Yahoo's latest bar is yesterday; exotic pairs with sparse history.
Related errors
- Failed to fetch exchange rates: #{rates_response.error.messa
- No chart data found for currency pair #{from}/#{to}
- API error (code: #{error_code}): #{error_message}
- No prices found for security #{symbol} on date #{date}
- Invalid response format: #{e.message}
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/37f9b606a6597aca.
Report an issue: GitHub.