we-promise/sure · error · IbkrItem::ReportParser::ParseError

Invalid IBKR Flex XML: missing FlexQueryResponse root.

Error message

Invalid IBKR Flex XML: missing FlexQueryResponse root.

What it means

validate_document! requires an //FlexQueryResponse element: the document parsed as XML but its root is not an IBKR Flex report. The response is structurally valid XML of the wrong shape — frequently IBKR's own error/ack XML.

Source

Thrown at app/models/ibkr_item/report_parser.rb:37

  def initialize(xml_body)
    @document = Nokogiri::XML(xml_body.to_s) { |config| config.strict.noblanks }
  rescue Nokogiri::XML::SyntaxError => e
    raise ParseError, "Invalid IBKR Flex XML: #{e.message}"
  end

  def parse
    validate_document!

    {
      metadata: root_metadata,
      accounts: flex_statements.map { |statement| parse_statement(statement) }
    }
  end

  private

    def validate_document!
      raise ParseError, "Invalid IBKR Flex XML: missing FlexQueryResponse root." unless @document.at_xpath("//FlexQueryResponse")
      raise ParseError, "Invalid IBKR Flex XML: no FlexStatement nodes found." if flex_statements.empty?
    end

    def flex_statements
      @document.xpath("//FlexStatement")
    end

    def root_metadata
      node_attributes(@document.at_xpath("//FlexQueryResponse"))
    end

    def parse_statement(statement)
      statement_data = node_attributes(statement)
      account_information = node_attributes(statement.at_xpath("./AccountInformation"))
      position_values = section_rows(statement, POSITION_VALUE_CONTAINER_NAMES, POSITION_VALUE_ROW_NAMES)
      cash_report = section_rows(statement, CASH_REPORT_CONTAINER_NAMES, CASH_REPORT_ROW_NAMES)
      equity_summary_in_base = section_rows(statement, EQUITY_SUMMARY_CONTAINER_NAMES, EQUITY_SUMMARY_ROW_NAMES)
      open_positions = section_rows(statement, OPEN_POSITION_CONTAINER_NAMES, OPEN_POSITION_ROW_NAMES)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Log @document.root.name (or the first 500 chars of the raw body) to see what IBKR actually returned
  2. If it is an IBKR error document, read its error code/message and fix credentials or query configuration accordingly
  3. Update fixtures to real FlexQueryResponse documents captured from a working Flex Query
Defensive patterns

Strategy: try-catch

Validate before calling

require 'nokogiri'
Nokogiri::XML(body).at_xpath('//FlexQueryResponse').present? # false => parse will raise the missing-root error

Try / catch

rescue IbkrItem::ReportParser::ParseError and branch on the message: 'missing FlexQueryResponse root' means wrong/unexpected document — inspect root name and IBKR error payloads before retrying

Prevention

When it happens

Trigger: The fetched document contains no FlexQueryResponse node: wrong endpoint or response envelope, an IBKR Flex Web Service error document, or a fixture generated from a different report type.

Common situations: IBKR returning an error XML for an invalid token or query id; middlewares rewriting responses; tests using XML fixtures that are valid but not Flex reports.

Related errors


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