{"record":{"id":"c5c6a5c855f58c7c","repo":"we-promise/sure","slug":"token-is-required","errorCode":null,"errorMessage":"token is required","messagePattern":"token is required","errorType":"exception","errorClass":"Provider::IbkrFlex::ConfigurationError","httpStatus":null,"severity":"error","filePath":"app/models/provider/ibkr_flex.rb","lineNumber":44,"sourceCode":"  POLL_INTERVAL = 3\n  MAX_POLL_ATTEMPTS = 20\n  PENDING_ERROR_CODES = %w[1004 1019].freeze\n\n  RETRYABLE_ERRORS = [\n    SocketError,\n    Net::OpenTimeout,\n    Net::ReadTimeout,\n    Errno::ECONNRESET,\n    Errno::ECONNREFUSED,\n    Errno::ETIMEDOUT,\n    EOFError\n  ].freeze\n\n  attr_reader :query_id, :token\n\n  def initialize(query_id:, token:)\n    raise ConfigurationError, \"query_id is required\" if query_id.blank?\n    raise ConfigurationError, \"token is required\" if token.blank?\n\n    @query_id = query_id.to_s.strip\n    @token = token.to_s.strip\n  end\n\n  def download_statement\n    reference_code = request_reference_code\n    poll_statement(reference_code)\n  end\n\n  private\n\n    def request_reference_code\n      response = with_retries(\"SendRequest\") do\n        self.class.get(\"/SendRequest\", query: { t: token, q: query_id, v: 3 })\n      end\n\n      xml = parse_xml(response.body)","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/ibkr_flex.rb#L26-L62","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: raises ConfigurationError deep in setup flow\nprovider = Provider::IbkrFlex.new(query_id:, token: credential.token)\n\n# after: explicit pre-check with actionable messaging\nif credential.token.blank?\n  raise ConfigurationError, \"IBKR Flex token missing — generate one in Client Portal (Flex Reporting)\"\nend\nprovider = Provider::IbkrFlex.new(query_id:, token: credential.token)","handlingStrategy":"validation","validationCode":"# Boundary check for the token before constructing the provider\nraise ArgumentError, \"IBKR Flex token missing — generate in Client Portal\" if token.to_s.strip.empty?","typeGuard":"def valid_ibkr_flex_token?(token)\n  token.to_s.strip.match?(\\A[A-Za-z0-9]{20,}\\z)\nend","tryCatchPattern":"begin\n  provider = Provider::IbkrFlex.new(query_id:, token:)\nrescue Provider::IbkrFlex::ConfigurationError => e\n  render_settings_error(field: :token, message: e.message)\nend","preventionTips":["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"],"tags":["ibkr","configuration","flex-token","missing-credential","validation"],"backgroundTag":"missing-configuration","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}