we-promise/sure · warning · StandardError

Import failed

Error message

Import failed

What it means

ArgumentError raised by validate_date_params! when validated_start_date < MAX_LOOKBACK_WINDOW.ago.to_date, with MAX_LOOKBACK_WINDOW = 10.years (app/models/provider/yahoo_finance.rb:35). The provider caps how far back the Yahoo chart API is queried; requesting older history is rejected client-side before any request. Together with the future-date check it brackets requests to a 10-year sliding window ending today.

Source

Thrown at app/models/enable_banking_item/syncer.rb:43

    unless import_result[:success]
      # A session-level auth failure detected mid-import flips the item to
      # requires_update — surface that as a graceful reconnect state, not a red
      # error. Transient/per-account failures leave status good and fall through
      # to a normal sync error that retries next time.
      if enable_banking_item.requires_update?
        sync.update!(status_text: "Re-authorization required") if sync.respond_to?(:status_text)
        collect_health_stats(sync, errors: nil)
        return
      end

      error_msg = import_result[:error]
      if error_msg.blank? && (import_result[:accounts_failed].to_i > 0 || import_result[:transactions_failed].to_i > 0)
        parts = []
        parts << "#{import_result[:accounts_failed]} #{'account'.pluralize(import_result[:accounts_failed])} failed" if import_result[:accounts_failed].to_i > 0
        parts << "#{import_result[:transactions_failed]} #{'transaction'.pluralize(import_result[:transactions_failed])} failed" if import_result[:transactions_failed].to_i > 0
        error_msg = parts.join(", ")
      end
      raise StandardError.new(error_msg.presence || "Import failed")
    end

    # Phase 2: Check account setup status and collect sync statistics
    sync.update!(status_text: "Checking account configuration...") if sync.respond_to?(:status_text)
    collect_setup_stats(sync, provider_accounts: enable_banking_item.enable_banking_accounts.includes(:account_provider, :account))

    unlinked_accounts = enable_banking_item.enable_banking_accounts.left_joins(:account_provider).where(account_providers: { id: nil })

    if unlinked_accounts.any?
      enable_banking_item.update!(pending_account_setup: true)
      sync.update!(status_text: "#{unlinked_accounts.count} accounts need setup...") if sync.respond_to?(:status_text)
    else
      enable_banking_item.update!(pending_account_setup: false)
    end

    # Phase 3: Process transactions for linked and visible accounts only
    linked_account_ids = enable_banking_item.enable_banking_accounts
      .joins(:account_provider)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Clamp start_date to MAX_LOOKBACK_WINDOW.ago.to_date (10.years.ago.to_date) before calling
  2. For older history, use a provider with deeper history (Tiingo/EODHD per docs/llm-guides/adding-a-securities-provider.md)
  3. Skip pre-cap records and record them as 'price unavailable' rather than failing the batch
  4. Make the cap visible in import/validation UX so users set expectations

Example fix

# before
provider.fetch_security_prices(symbol: s, start_date: Date.new(2005, 6, 1), end_date: Date.current)

# after
earliest = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date
provider.fetch_security_prices(symbol: s, start_date: [Date.new(2005, 6, 1), earliest].max, end_date: Date.current)
Defensive patterns

Strategy: validation

Validate before calling

earliest = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date # 10 years
start_date = [start_date.to_date, earliest].max

Try / catch

begin
  provider.fetch_security_prices(symbol: sym, start_date: s, end_date: e)
rescue ArgumentError => e
  raise unless e.message.include?("maximum lookback window")
  s = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date
  retry
end

Prevention

When it happens

Trigger: Backfilling prices for a position opened 12 years ago; hardcoding a historical epoch (1990-01-01) as start_date; long-lived securities where 'since inception' predates the cap; tests with ancient fixtures.

Common situations: Users importing decades-old trade history from brokers; migration scripts syncing full account history; misunderstanding that the cap is provider-wide, not per-request.

Related errors


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