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

token is required

Error message

token is required

What it means

Raised as Provider::IbkrFlex::ConfigurationError when constructing Provider::IbkrFlex with a blank token. The token is the Flex Web Service credential generated in IBKR Client Portal ('Flex Access Token'); without it every request to SendRequest would be rejected by IBKR. initialize fails fast on blank tokens (nil, empty, whitespace) before any HTTP traffic, mirroring the query_id check.

Source

Thrown at app/models/provider/ibkr_flex.rb:44

  POLL_INTERVAL = 3
  MAX_POLL_ATTEMPTS = 20
  PENDING_ERROR_CODES = %w[1004 1019].freeze

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

  attr_reader :query_id, :token

  def initialize(query_id:, token:)
    raise ConfigurationError, "query_id is required" if query_id.blank?
    raise ConfigurationError, "token is required" if token.blank?

    @query_id = query_id.to_s.strip
    @token = token.to_s.strip
  end

  def download_statement
    reference_code = request_reference_code
    poll_statement(reference_code)
  end

  private

    def request_reference_code
      response = with_retries("SendRequest") do
        self.class.get("/SendRequest", query: { t: token, q: query_id, v: 3 })
      end

      xml = parse_xml(response.body)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Generate a token in IBKR Client Portal: Settings → Account Settings → Flex Reporting → 'Generate Flex Token' (or re-use an active one)
  2. Save the token into the account's IBKR Flex credentials and rebuild the provider
  3. Check the token was not pasted into the query_id field (tokens are long alphanumeric; query IDs are short numeric)
  4. Add UI-level presence checks so the missing field is named before Provider::IbkrFlex is constructed
  5. If regenerating, note IBKR allows a limited number of active tokens; deactivate stale ones to avoid confusion

Example fix

# before: raises ConfigurationError deep in setup flow
provider = Provider::IbkrFlex.new(query_id:, token: credential.token)

# after: explicit pre-check with actionable messaging
if credential.token.blank?
  raise ConfigurationError, "IBKR Flex token missing — generate one in Client Portal (Flex Reporting)"
end
provider = Provider::IbkrFlex.new(query_id:, token: credential.token)
Defensive patterns

Strategy: validation

Validate before calling

# Boundary check for the token before constructing the provider
raise ArgumentError, "IBKR Flex token missing — generate in Client Portal" if token.to_s.strip.empty?

Type guard

def valid_ibkr_flex_token?(token)
  token.to_s.strip.match?(\A[A-Za-z0-9]{20,}\z)
end

Try / catch

begin
  provider = Provider::IbkrFlex.new(query_id:, token:)
rescue Provider::IbkrFlex::ConfigurationError => e
  render_settings_error(field: :token, message: e.message)
end

Prevention

When it happens

Trigger: Provider::IbkrFlex.new(token: nil_or_blank) — user completed setup without generating/pasting a Flex token, token stored under the wrong credential key, or a fixture/ENV var empty. Raises at construction time; download_statement is never reached.

Common situations: Users pasting the Flex Query ID into both fields, tokens expiring or being regenerated in Client Portal leaving the stored copy empty after a re-import, copy/paste failures (trailing newline handled by strip, but empty paste is not), and automated setups that only provision query_id.

Related errors


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