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

api_secret is required

Error message

api_secret is required

What it means

Provider::Trading212::ConfigurationError raised in the constructor when the required api_secret keyword argument is blank. The client signs every request with Basic auth (Base64 of api_key:api_secret), so a missing secret makes authenticated calls impossible and instantiation is refused immediately.

Source

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

  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")
  end

View on GitHub (pinned to e69894adb9)

Solutions

  1. Set TRADING212_API_SECRET in the environment (and .env.local for development) and pass it to the constructor
  2. Validate both credentials up front in the caller: return a 'credentials incomplete' state to the user instead of an exception
  3. Re-copy the secret from Trading 212's Settings > API page — key and secret must come from the same generation
  4. If deploying, confirm the secret is present in the deployment environment's secret store, not just locally

Example fix

// before
client = Provider::Trading212.new(api_key: key, api_secret: params[:api_secret])

// after
secret = params[:api_secret].presence
return render_error(:api_secret_blank) if secret.nil?

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

Strategy: validation

Validate before calling

attrs = { api_key: key, api_secret: secret }
missing = attrs.select { |_, v| v.blank? }.keys
raise ArgumentError, "Trading 212 credentials missing: #{missing.join(', ')}" if missing.any?

Try / catch

begin
  Provider::Trading212.new(api_key: key, api_secret: secret)
rescue Provider::Trading212::ConfigurationError => e
  redirect_to provider_settings_path, alert: e.message
end

Prevention

When it happens

Trigger: Calling Provider::Trading212.new(api_key: "key", api_secret: nil) or api_secret: ""; ENV["TRADING212_API_SECRET"] unset; the settings UI stored the key but the secret field was left blank.

Common situations: Trading 212's API key/secret pair was only half-copied into environment config; secret exists in production ENV but not in CI or the developer's .env.local; a secrets rotation replaced the key but the secret propagation failed.

Related errors


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