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
- Generate a token in IBKR Client Portal: Settings → Account Settings → Flex Reporting → 'Generate Flex Token' (or re-use an active one)
- Save the token into the account's IBKR Flex credentials and rebuild the provider
- Check the token was not pasted into the query_id field (tokens are long alphanumeric; query IDs are short numeric)
- Add UI-level presence checks so the missing field is named before Provider::IbkrFlex is constructed
- 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
- Add a 'Test connection' button that constructs the provider so misconfigurations surface at setup time
- Document where to generate the Flex token (Client Portal → Flex Reporting) directly in the settings UI
- Store credentials via the credential store, never in plaintext ENV snapshots
- Validate token shape (long alphanumeric) at save time
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
- query_id is required
- Either API token or all three username/document/password cre
- {result.error}
- {e.record.errors.full_messages.to_sentence.presence || e.mes
- Anthropic Model is required when a custom Base URL is set.
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/c5c6a5c855f58c7c.
Report an issue: GitHub.