{"record":{"id":"47754b802b65145b","repo":"we-promise/sure","slug":"no-prices-found-for-security-symbol-on-date-d-47754b","errorCode":null,"errorMessage":"No prices found for security #{symbol} on date #{date}","messagePattern":"No prices found for security #(.+?) on date #(.+?)","errorType":"exception","errorClass":"Provider::Tiingo::InvalidSecurityPriceError","httpStatus":null,"severity":"warning","filePath":"app/models/provider/tiingo.rb","lineNumber":163,"sourceCode":"\n      SecurityInfo.new(\n        symbol: parsed[\"ticker\"] || symbol,\n        name: parsed[\"name\"],\n        links: nil,\n        logo_url: nil,\n        description: parsed[\"description\"],\n        kind: nil,\n        exchange_operating_mic: resolved_mic\n      )\n    end\n  end\n\n  def fetch_security_price(symbol:, exchange_operating_mic: nil, date:)\n    with_provider_response do\n      historical_data = fetch_security_prices(symbol:, exchange_operating_mic:, start_date: date, end_date: date)\n\n      raise historical_data.error if historical_data.error.present?\n      raise InvalidSecurityPriceError, \"No prices found for security #{symbol} on date #{date}\" if historical_data.data.blank?\n\n      historical_data.data.first\n    end\n  end\n\n  def fetch_security_prices(symbol:, exchange_operating_mic: nil, start_date:, end_date:)\n    with_provider_response do\n      throttle_request\n      track_symbol(symbol)\n\n      response = client.get(\"#{base_url}/tiingo/daily/#{CGI.escape(symbol)}/prices\") do |req|\n        req.params[\"startDate\"] = start_date.to_s\n        req.params[\"endDate\"] = end_date.to_s\n      end\n\n      parsed = JSON.parse(response.body)\n      check_api_error!(parsed)\n","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/tiingo.rb#L145-L181","documentation":"fetch_security_price narrows to a single day by calling fetch_security_prices(symbol:, start_date: date, end_date: date) and raising InvalidSecurityPriceError when the returned data array is empty. An empty array means Tiingo's daily-prices endpoint accepted the request (no API error was raised) but has no candle rows for that symbol on that date. The most common legitimate cause is a non-trading day; it can also mean the symbol has no end-of-day data (unsupported asset class) or was listed after the date.","triggerScenarios":"Calling fetch_security_price(symbol: 'AAPL', date: Date.new(2026, 8, 22)) where that date is a Saturday/Sunday or market holiday; requesting a date before the security's IPO; requesting a forex/crypto symbol on the /tiingo/daily/ equities endpoint which only covers EOD equity data.","commonSituations":"Manual valuation flows letting users pick arbitrary calendar dates; job that prices securities 'as of today' running on weekends/holidays; portfolios with delisted tickers whose history was trimmed; symbols from other exchanges Tiingo daily doesn't cover.","solutions":["Validate the date is an exchange trading day before calling, or walk back to the previous trading day","Confirm the symbol actually returns data: fetch_security_prices over a wider range and inspect which dates exist","If the symbol is not an equity EOD series (forex/crypto/fund), route it to the provider/endpoint that supports it instead of /tiingo/daily"],"exampleFix":"# before\nprice = provider.fetch_security_price(symbol: symbol, date: date)\n\n# after\ntrading_day = TradeDate.previous_on_or_before(date, exchange_mic: exchange_operating_mic)\nprice = provider.fetch_security_price(symbol: symbol, exchange_operating_mic: exchange_operating_mic, date: trading_day)","handlingStrategy":"fallback","validationCode":"# Check the calendar before asking for a price\ndate = TradingCalendar.previous_trading_day(date) unless TradingCalendar.trading_day?(date)","typeGuard":null,"tryCatchPattern":"begin\n  price = provider.fetch_security_price(symbol: sym, date: date)\nrescue Provider::Tiingo::InvalidSecurityPriceError\n  price = nil # caller falls back to last known price\nend","preventionTips":["Use ranged fetch_security_prices once and pick the wanted date client-side instead of exact-date calls","Cache last-known prices so a missing single day degrades gracefully"],"tags":["tiingo","price-data","no-data","trading-day","securities"],"backgroundTag":"no-price-data-for-date","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}