{"record":{"id":"216cb88690434c00","repo":"we-promise/sure","slug":"import-failed","errorCode":null,"errorMessage":"Import failed","messagePattern":"Import failed","errorType":"exception","errorClass":"StandardError","httpStatus":null,"severity":"warning","filePath":"app/models/enable_banking_item/syncer.rb","lineNumber":43,"sourceCode":"    unless import_result[:success]\n      # A session-level auth failure detected mid-import flips the item to\n      # requires_update — surface that as a graceful reconnect state, not a red\n      # error. Transient/per-account failures leave status good and fall through\n      # to a normal sync error that retries next time.\n      if enable_banking_item.requires_update?\n        sync.update!(status_text: \"Re-authorization required\") if sync.respond_to?(:status_text)\n        collect_health_stats(sync, errors: nil)\n        return\n      end\n\n      error_msg = import_result[:error]\n      if error_msg.blank? && (import_result[:accounts_failed].to_i > 0 || import_result[:transactions_failed].to_i > 0)\n        parts = []\n        parts << \"#{import_result[:accounts_failed]} #{'account'.pluralize(import_result[:accounts_failed])} failed\" if import_result[:accounts_failed].to_i > 0\n        parts << \"#{import_result[:transactions_failed]} #{'transaction'.pluralize(import_result[:transactions_failed])} failed\" if import_result[:transactions_failed].to_i > 0\n        error_msg = parts.join(\", \")\n      end\n      raise StandardError.new(error_msg.presence || \"Import failed\")\n    end\n\n    # Phase 2: Check account setup status and collect sync statistics\n    sync.update!(status_text: \"Checking account configuration...\") if sync.respond_to?(:status_text)\n    collect_setup_stats(sync, provider_accounts: enable_banking_item.enable_banking_accounts.includes(:account_provider, :account))\n\n    unlinked_accounts = enable_banking_item.enable_banking_accounts.left_joins(:account_provider).where(account_providers: { id: nil })\n\n    if unlinked_accounts.any?\n      enable_banking_item.update!(pending_account_setup: true)\n      sync.update!(status_text: \"#{unlinked_accounts.count} accounts need setup...\") if sync.respond_to?(:status_text)\n    else\n      enable_banking_item.update!(pending_account_setup: false)\n    end\n\n    # Phase 3: Process transactions for linked and visible accounts only\n    linked_account_ids = enable_banking_item.enable_banking_accounts\n      .joins(:account_provider)","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/enable_banking_item/syncer.rb#L25-L61","documentation":"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.","triggerScenarios":"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.","commonSituations":"Users importing decades-old trade history from brokers; migration scripts syncing full account history; misunderstanding that the cap is provider-wide, not per-request.","solutions":["Clamp start_date to MAX_LOOKBACK_WINDOW.ago.to_date (10.years.ago.to_date) before calling","For older history, use a provider with deeper history (Tiingo/EODHD per docs/llm-guides/adding-a-securities-provider.md)","Skip pre-cap records and record them as 'price unavailable' rather than failing the batch","Make the cap visible in import/validation UX so users set expectations"],"exampleFix":"# before\nprovider.fetch_security_prices(symbol: s, start_date: Date.new(2005, 6, 1), end_date: Date.current)\n\n# after\nearliest = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date\nprovider.fetch_security_prices(symbol: s, start_date: [Date.new(2005, 6, 1), earliest].max, end_date: Date.current)","handlingStrategy":"validation","validationCode":"earliest = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date # 10 years\nstart_date = [start_date.to_date, earliest].max","typeGuard":null,"tryCatchPattern":"begin\n  provider.fetch_security_prices(symbol: sym, start_date: s, end_date: e)\nrescue ArgumentError => e\n  raise unless e.message.include?(\"maximum lookback window\")\n  s = Provider::YahooFinance::MAX_LOOKBACK_WINDOW.ago.to_date\n  retry\nend","preventionTips":["Clamp start dates to the 10-year window before importing old trades","Use a deep-history provider for pre-caps data","Surface the lookback cap in import UX"],"tags":["yahoo-finance","date-validation","lookback-limit","backfill"],"backgroundTag":"date-range-limit-exceeded","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}