we-promise/sure · error · ApiError

IBKR Flex did not return a reference code.

Error message

IBKR Flex did not return a reference code.

What it means

GET /SendRequest?t=token&q=query_id&v=3 succeeded at the transport level and returned XML with neither //ErrorCode (any ErrorCode would have been raised earlier by response_error) nor a usable //ReferenceCode. The expected contract is SendRequest returning a ReferenceCode that GetStatement later polls; a blank one means IBKR answered with an unexpected-but-non-error body.

Source

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

  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)
      error = response_error(xml, response)
      raise error if error

      reference_code = xml.at_xpath("//ReferenceCode")&.text.to_s.strip
      raise ApiError.new("IBKR Flex did not return a reference code.", status_code: response.code, response_body: response.body) if reference_code.blank?

      reference_code
    end

    def poll_statement(reference_code)
      attempts = 0

      loop do
        attempts += 1
        response = with_retries("GetStatement") do
          self.class.get("/GetStatement", query: { t: token, q: reference_code, v: 3 })
        end

        xml = parse_xml(response.body)
        return response.body if xml.at_xpath("//FlexQueryResponse")

        error = response_error(xml, response)
        if error.is_a?(ApiError) && PENDING_ERROR_CODES.include?(error.error_code.to_s)

View on GitHub (pinned to e69894adb9)

Solutions

  1. Verify both values in IBKR Client Portal (Performance & Reports > Flex Queries > Flex Web Service): the token and the numeric query ID of a query with at least one data section enabled
  2. Reproduce manually: curl "https://ndcdyn.interactivebrokers.com/AccountManagement/FlexWebService/SendRequest?t=<token>&q=<query>&v=3" and inspect the XML
  3. Inspect e.response_body on the raised ApiError - it carries the exact XML that lacked the ReferenceCode
  4. Regenerate the Flex token, wait a few minutes for propagation, and retry

Example fix

# before
def download
  Provider::IbkrFlex.new(query_id: qid, token: tok).download_statement
end

# after
def download
  Provider::IbkrFlex.new(query_id: qid, token: tok).download_statement
rescue Provider::IbkrFlex::ApiError => e
  Rails.logger.error("SendRequest body without ReferenceCode: #{e.response_body}")
  raise
end
Defensive patterns

Strategy: try-catch

Validate before calling

# IBKR Flex query IDs are numeric; tokens are long alphanumeric strings
fail "query_id must be numeric" unless query_id.to_s.match?(/\A\d+\z/)
fail "token looks wrong (expect 30+ chars)" unless token.to_s.length >= 30
flex = Provider::IbkrFlex.new(query_id: query_id, token: token)

Type guard

def ibkr_missing_reference_code?(error)
  error.is_a?(Provider::IbkrFlex::ApiError) &&
    error.message.include?("did not return a reference code")
end

Try / catch

begin
  flex.download_statement
rescue Provider::IbkrFlex::ApiError => e
  if e.message.include?("did not return a reference code")
    Rails.logger.error("SendRequest returned: #{e.response_body}") # exact XML for diagnosis
    CredentialAlert.notify(:ibkr_flex, account) # config problem, not transient
  end
  raise
end

Prevention

When it happens

Trigger: The token/query_id pair passes basic validation but the Flex Query itself is empty or disabled (no data sections selected), so IBKR returns a stub body; a response envelope change drops or renames ReferenceCode; the token was regenerated and the old query association returns an inert response.

Common situations: Copy-pasting the Flex Query *name* instead of its numeric ID (or vice versa), creating a Flex Query in Client Portal without enabling any report sections, regenerating the Flex token but keeping a stale query ID, IBKR quietly changing the SendRequest response shape.

Related errors


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