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
- 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
- Reproduce manually: curl "https://ndcdyn.interactivebrokers.com/AccountManagement/FlexWebService/SendRequest?t=<token>&q=<query>&v=3" and inspect the XML
- Inspect e.response_body on the raised ApiError - it carries the exact XML that lacked the ReferenceCode
- 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
- Store query_id and token exactly as shown in Client Portal > Flex Queries, and lint query_id as numeric
- Ensure the Flex Query has at least one data section enabled before using it
- Add a smoke-test job that runs SendRequest after any credential rotation
- Log e.response_body whenever this fires - the XML tells you exactly what IBKR sent
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
- Invalid IBKR Flex XML: missing FlexQueryResponse root.
- Invalid IBKR Flex XML: no FlexStatement nodes found.
- Invalid IBKR Flex XML: missing account identifier in FlexSta
- IBKR Flex statement is still being generated.
- Network error after #{max_retries} retries: #{e.message}
AI-assisted analysis of we-promise/sure@e69894adb9 (2026-08-21).
Data as JSON: /api/errors/474efe11138ac570.
Report an issue: GitHub.