we-promise/sure · error · StandardError

Trading 212 provider is not configured

Error message

Trading 212 provider is not configured

What it means

Raised as a plain StandardError by Trading212Item#import_latest_data (app/models/trading212_item.rb:35) when trading212_provider returns nil. The provider factory (Trading212Item::Provided#trading212_provider, app/models/trading212_item/provided.rb:4) returns nil unless credentials_configured? is true, i.e. both api_key and api_secret are present. So the 'provider is not configured' text really means 'this item is missing one or both stored credentials'. The rescue also writes a DebugLogEntry (category sync, provider_key trading212) before re-raising.

Source

Thrown at app/models/trading212_item.rb:35

  validates :api_secret, presence: true, on: :create

  scope :active, -> { where(scheduled_for_deletion: false) }
  scope :syncable, -> { active.where.not(api_key: [ nil, "" ]) }
  scope :ordered, -> { order(created_at: :desc) }
  scope :needs_update, -> { where(status: :requires_update) }

  def destroy_later
    update!(scheduled_for_deletion: true)
    DestroyJob.perform_later(self)
  end

  def credentials_configured?
    api_key.present? && api_secret.present?
  end

  def import_latest_data
    provider = trading212_provider
    raise StandardError, "Trading 212 provider is not configured" unless provider

    Trading212Item::Importer.new(self, provider: provider).import
  rescue => e
    DebugLogEntry.capture(
      category: "sync",
      level: "error",
      message: "Trading212Item #{id} - Failed to import data: #{e.message}",
      source: "trading212",
      family: family,
      provider_key: "trading212"
    )
    raise
  end

  def process_accounts
    return [] if trading212_accounts.empty?

    linked_trading212_accounts.includes(account_provider: :account).each_with_object([]) do |t212_account, results|

View on GitHub (pinned to e69894adb9)

Solutions

  1. Re-enter the Trading 212 API key and secret on the item (settings UI or item.update!(api_key: ..., api_secret: ...)) so credentials_configured? returns true.
  2. Guard the call site: skip or mark requires_update when item.credentials_configured? is false instead of letting StandardError surface.
  3. If it fires right after an encryption-key change, verify ACTIVE_RECORD_ENCRYPTION_* env vars match the ones used when the secrets were stored.
  4. Check /settings/debug (DebugLogEntry, source trading212) for the captured entry to confirm which item and family are affected.

Example fix

// before
item.import_latest_data # raises when api_key/api_secret blank

// after
if item.credentials_configured?
  item.import_latest_data
else
  item.update!(status: :requires_update)
end
Defensive patterns

Strategy: validation

Validate before calling

raise ArgumentError, 'configure credentials first' unless item.credentials_configured?
item.import_latest_data

Type guard

item.credentials_configured? # -> api_key.present? && api_secret.present?

Try / catch

begin
  item.import_latest_data
rescue StandardError => e
  # message is already captured to DebugLogEntry (source: trading212)
  Rails.logger.warn("trading212 import failed: #{e.message}")
  item.update!(status: :requires_update)
end

Prevention

When it happens

Trigger: Calling item.import_latest_data on a Trading212Item whose api_key or api_secret is blank: items created before credentials were added, secrets wiped by an encryption-key rotation or a failed deterministic decrypt, or records loaded after api_key was cleared. Any sync job (Syncable) that drives perform_sync -> import_latest_data without first checking credentials_configured?.

Common situations: Re-encrypting/migrating the database without ACTIVE_RECORD_ENCRYPTION keys leaving credential columns unreadable; manually nulling credentials in a console; racing a destroy_later (scheduled_for_deletion) item that still gets enqueued for one last sync.

Related errors


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