we-promise/sure · error · Provider::Trading212::ConfigurationError

api_key is required

Error message

api_key is required

What it means

Provider::Trading212::ConfigurationError raised in the constructor when the required api_key keyword argument is blank (nil or empty/whitespace string). Trading 212's API uses Basic auth built from api_key:api_secret, so the client refuses to instantiate without a key. This fails fast before any HTTP request is made.

Source

Thrown at app/models/provider/trading212.rb:40

  MAX_PAGES = 200
  PAGE_LIMIT = 50

  RETRYABLE_ERRORS = [
    SocketError,
    Net::OpenTimeout,
    Net::ReadTimeout,
    Errno::ECONNRESET,
    Errno::ECONNREFUSED,
    Errno::ETIMEDOUT,
    EOFError
  ].freeze

  default_options.merge!({ timeout: 60 }.merge(httparty_ssl_options))

  attr_reader :api_key, :api_secret, :environment

  def initialize(api_key:, api_secret:, environment: "live")
    raise ConfigurationError, "api_key is required" if api_key.blank?
    raise ConfigurationError, "api_secret is required" if api_secret.blank?
    raise ConfigurationError, "Invalid environment: #{environment}" unless %w[live demo].include?(environment.to_s)

    @api_key = api_key.to_s.strip
    @api_secret = api_secret.to_s.strip
    @environment = environment.to_s
  end

  def fetch_account_summary
    get("/equity/account/summary")
  end

  def fetch_positions
    get("/equity/positions")
  end

  def fetch_instruments
    get("/equity/metadata/instruments")

View on GitHub (pinned to e69894adb9)

Solutions

  1. Set the API key before constructing: export TRADING212_API_KEY=... (or add it to .env.local) and pass it through
  2. Verify the value is present and non-empty in the code path that builds the provider: raise a user-facing validation error if credentials are missing instead of letting the provider raise
  3. If the key comes from a settings/account record, check record.api_key.present? before instantiating Provider::Trading212
  4. Confirm you copied the full key from Trading 212's Settings > API section (keys are long; partial pastes are blank after strip)

Example fix

// before
client = Provider::Trading212.new(
  api_key: ENV["TRADING212_API_KEY"],
  api_secret: ENV["TRADING212_API_SECRET"]
)

// after
api_key = ENV["TRADING212_API_KEY"]
api_secret = ENV["TRADING212_API_SECRET"]
raise ArgumentError, "Set TRADING212_API_KEY and TRADING212_API_SECRET" if api_key.blank? || api_secret.blank?

client = Provider::Trading212.new(api_key: api_key, api_secret: api_secret)
Defensive patterns

Strategy: validation

Validate before calling

api_key = ENV["TRADING212_API_KEY"]
raise ArgumentError, "TRADING212_API_KEY is blank" if api_key.blank?
# or, from a settings record:
raise "Connect Trading 212 and enter an API key first" if account_provider.api_key.blank?

Try / catch

begin
  client = Provider::Trading212.new(api_key:, api_secret:, environment: "live")
rescue Provider::Trading212::ConfigurationError => e
  # config problem, not transient — show setup UI, never retry
end

Prevention

When it happens

Trigger: Calling Provider::Trading212.new(api_key: nil, api_secret: "secret"), passing api_key: "" or " " (whitespace survives .blank? check), or reading the key from an ENV var / settings record that was never set (ENV["TRADING212_API_KEY"] returns nil).

Common situations: Fresh environment where TRADING212_API_KEY is not in .env.local; a user connects a Trading 212 account but never entered an API key in the settings UI; a YAML/credentials file renamed the key; test suite constructing the provider without stubbing the key.

Related errors


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