we-promise/sure · warning · Provider::BinancePublic::InvalidSecurityPriceError

No price found for #{symbol} on #{date}

Error message

No price found for #{symbol} on #{date}

What it means

Raised by Provider::BinancePublic#fetch_security_price (as InvalidSecurityPriceError, defined as Class.new(Error) at binance_public.rb:6) when fetch_security_prices for a single day succeeds but returns an empty data set. It can also re-raise historical.error first; this specific message fires only when historical.data.blank? for the requested date.

Source

Thrown at app/models/provider/binance_public.rb:185

        logo_url: nil,
        description: nil,
        kind: "crypto",
        exchange_operating_mic: exchange_operating_mic
      )
    end
  end

  def fetch_security_price(symbol:, exchange_operating_mic:, date:)
    with_provider_response do
      historical = fetch_security_prices(
        symbol: symbol,
        exchange_operating_mic: exchange_operating_mic,
        start_date: date,
        end_date: date
      )

      raise historical.error if historical.error.present?
      raise InvalidSecurityPriceError, "No price found for #{symbol} on #{date}" if historical.data.blank?

      historical.data.first
    end
  end

  def fetch_security_prices(symbol:, exchange_operating_mic:, start_date:, end_date:)
    with_provider_response do
      parsed = parse_ticker(symbol)
      raise InvalidSecurityPriceError, "Unsupported Binance ticker: #{symbol}" if parsed.nil?

      if parsed[:stablecoin]
        next stablecoin_prices(symbol, parsed, start_date, end_date, exchange_operating_mic)
      end

      binance_pair = parsed[:binance_pair]
      display_currency = parsed[:display_currency]
      prices = []
      cursor = start_date

View on GitHub (pinned to e69894adb9)

Solutions

  1. Confirm the pair's listing date (first available kline on Binance) and clamp start_date to it.
  2. Reject future dates before calling: no price can exist for date > Date.today.
  3. If the price is genuinely missing, fall back to the nearest earlier close or the security's last known price rather than failing.
  4. Rescue Provider::BinancePublic::InvalidSecurityPriceError per-date so one gap does not abort a range import.

Example fix

# before
price = provider.fetch_security_price(symbol: "BTCUSDT", exchange_operating_mic: "BINANCE", date: Date.new(2015, 1, 1))

# after
begin
  price = provider.fetch_security_price(symbol: "BTCUSDT", exchange_operating_mic: "BINANCE", date: date)
rescue Provider::BinancePublic::InvalidSecurityPriceError
  price = nil # or last known close; skip the day instead of aborting the sync
end
Defensive patterns

Strategy: fallback

Validate before calling

return if date > Date.today # no price can exist in the future
return if listing_date.present? && date < listing_date # before the pair traded

Type guard

def price_gap?(err)
  err.is_a?(Provider::BinancePublic::InvalidSecurityPriceError) && err.message.start_with?("No price found")
end

Try / catch

begin
  price = provider.fetch_security_price(symbol: sym, exchange_operating_mic: mic, date: date)
rescue Provider::BinancePublic::InvalidSecurityPriceError
  price = last_known_close_before(sym, date) # fall back to nearest earlier close
end

Prevention

When it happens

Trigger: Requesting a date before the pair was listed on Binance (e.g. a 2019 price for a 2021 coin); requesting a future date; a UTC day on which the pair had no kline data (extremely illiquid/delisted books); date boundary mismatches where the caller's timezone shifts the requested day outside available klines.

Common situations: Backfills that start from a portfolio creation date rather than the coin's listing date; securities whose created_at predates the actual listing; timezone handling passing local dates that resolve to empty UTC windows; retrying recently added coins whose history starts later than the account.

Related errors


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