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

Invalid environment: #{environment}

Error message

Invalid environment: #{environment}

What it means

Provider::Trading212::ConfigurationError raised when the environment argument is not exactly "live" or "demo" (case-sensitive after to_s). The environment selects the base URI: live.trading212.com vs demo.trading212.com, so an unknown value has no endpoint to target.

Source

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

  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. Pass exactly "live" or "demo": Provider::Trading212.new(api_key:, api_secret:, environment: "demo")
  2. Whitelist and normalize in the caller before constructing: env = %w[live demo].include?(env.to_s.downcase) ? env.to_s.downcase : nil, and surface a validation message for anything else
  3. If the value comes from a form, store the machine value ("live"/"demo") not the display label
  4. Omit the argument entirely when you want the default "live" environment

Example fix

// before
Provider::Trading212.new(api_key:, api_secret:, environment: params[:environment]) # "Live" -> raises

// after
env = params[:environment].to_s.downcase
env = "live" unless %w[live demo].include?(env)
Provider::Trading212.new(api_key:, api_secret:, environment: env)
Defensive patterns

Strategy: validation

Validate before calling

environment = params[:environment].to_s.downcase
unless %w[live demo].member?(environment)
  raise ArgumentError, "environment must be 'live' or 'demo', got #{environment.inspect}"
end

Try / catch

begin
  Provider::Trading212.new(api_key:, api_secret:, environment: env)
rescue Provider::Trading212::ConfigurationError => e
  # treat as programmer/form error — do not retry, fix the input
end

Prevention

When it happens

Trigger: Passing environment: "production", "Live" (capital L), "sandbox", "test", or a symbol like :live is fine (to_s) but :prod fails; passing nil (default "live" only applies when the arg is omitted, nil explicitly fails the include? check after to_s → "").

Common situations: UI dropdown saving a label like "Live account" instead of the value "live"; a config file renamed environments to production/staging; passing an unvalidated user-supplied string straight through.

Related errors


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