{"record":{"id":"ad74dfcce5066165","repo":"we-promise/sure","slug":"invalid-ibkr-flex-xml-missing-flexqueryresponse-r","errorCode":null,"errorMessage":"Invalid IBKR Flex XML: missing FlexQueryResponse root.","messagePattern":"Invalid IBKR Flex XML: missing FlexQueryResponse root\\.","errorType":"exception","errorClass":"IbkrItem::ReportParser::ParseError","httpStatus":null,"severity":"error","filePath":"app/models/ibkr_item/report_parser.rb","lineNumber":37,"sourceCode":"  def initialize(xml_body)\n    @document = Nokogiri::XML(xml_body.to_s) { |config| config.strict.noblanks }\n  rescue Nokogiri::XML::SyntaxError => e\n    raise ParseError, \"Invalid IBKR Flex XML: #{e.message}\"\n  end\n\n  def parse\n    validate_document!\n\n    {\n      metadata: root_metadata,\n      accounts: flex_statements.map { |statement| parse_statement(statement) }\n    }\n  end\n\n  private\n\n    def validate_document!\n      raise ParseError, \"Invalid IBKR Flex XML: missing FlexQueryResponse root.\" unless @document.at_xpath(\"//FlexQueryResponse\")\n      raise ParseError, \"Invalid IBKR Flex XML: no FlexStatement nodes found.\" if flex_statements.empty?\n    end\n\n    def flex_statements\n      @document.xpath(\"//FlexStatement\")\n    end\n\n    def root_metadata\n      node_attributes(@document.at_xpath(\"//FlexQueryResponse\"))\n    end\n\n    def parse_statement(statement)\n      statement_data = node_attributes(statement)\n      account_information = node_attributes(statement.at_xpath(\"./AccountInformation\"))\n      position_values = section_rows(statement, POSITION_VALUE_CONTAINER_NAMES, POSITION_VALUE_ROW_NAMES)\n      cash_report = section_rows(statement, CASH_REPORT_CONTAINER_NAMES, CASH_REPORT_ROW_NAMES)\n      equity_summary_in_base = section_rows(statement, EQUITY_SUMMARY_CONTAINER_NAMES, EQUITY_SUMMARY_ROW_NAMES)\n      open_positions = section_rows(statement, OPEN_POSITION_CONTAINER_NAMES, OPEN_POSITION_ROW_NAMES)","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/ibkr_item/report_parser.rb#L19-L55","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Log @document.root.name (or the first 500 chars of the raw body) to see what IBKR actually returned","If it is an IBKR error document, read its error code/message and fix credentials or query configuration accordingly","Update fixtures to real FlexQueryResponse documents captured from a working Flex Query"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"require 'nokogiri'\nNokogiri::XML(body).at_xpath('//FlexQueryResponse').present? # false => parse will raise the missing-root error","typeGuard":null,"tryCatchPattern":"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","preventionTips":["Validate the root element before handing a document to the parser","Pin fixtures to real FlexQueryResponse documents","On IBKR error XML, extract and log the embedded ErrorCode/ErrorMessage instead of re-fetching blindly"],"tags":["ibkr","xml","flex-query","schema"],"backgroundTag":"xml-schema-validation-failed","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}