@@ -2,18 +2,18 @@ import axios, { AxiosInstance } from "axios";
22import { Logger } from "./logger.js" ;
33import { parseStringPromise } from "xml2js" ;
44
5- export interface FlexQueryClientConfig {
5+ interface FlexQueryClientConfig {
66 token : string ;
77}
88
9- export interface FlexQueryResponse {
9+ interface FlexQueryResponse {
1010 referenceCode ?: string ;
1111 url ?: string ;
1212 error ?: string ;
1313 errorCode ?: string ;
1414}
1515
16- export interface FlexStatementResponse {
16+ interface FlexStatementResponse {
1717 data ?: string ; // XML data
1818 error ?: string ;
1919 errorCode ?: string ;
@@ -24,6 +24,21 @@ export interface FlexStatementResponse {
2424 * API Documentation: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
2525 */
2626export class FlexQueryClient {
27+ // IB Flex Web Service error codes that mean "try again shortly" — the statement
28+ // is being prepared. All other Fail codes are terminal (bad token, invalid query, etc.).
29+ private static readonly TRANSIENT_GET_STATEMENT_ERROR_CODES = new Set ( [
30+ "1001" , // Statement could not be generated at this time
31+ "1004" , // Statement is incomplete at this time
32+ "1005" , // Settlement data is not ready
33+ "1006" , // FIFO P/L data is not ready
34+ "1007" , // MTM P/L data is not ready
35+ "1008" , // MTM and FIFO P/L data is not ready
36+ "1009" , // Server is under heavy load
37+ "1018" , // Too many requests from this token
38+ "1019" , // Statement generation in progress
39+ "1021" , // Statement could not be retrieved at this time
40+ ] ) ;
41+
2742 private client : AxiosInstance ;
2843 private token : string ;
2944 // Fixed: gdcdyn → ndcdyn, /Universal/servlet → /AccountManagement/FlexWebService
@@ -182,16 +197,21 @@ export class FlexQueryClient {
182197 const statementResponse = await this . getStatement ( sendResponse . referenceCode ) ;
183198
184199 if ( statementResponse . error ) {
185- // Check if it's a "not ready yet" error
186- if (
187- statementResponse . errorCode === "1019" || // Statement generation in progress
188- statementResponse . error . includes ( "in progress" ) ||
189- statementResponse . error . includes ( "not ready" )
190- ) {
191- Logger . log ( `[FLEX-QUERY] Statement not ready yet, retrying...` ) ;
200+ const code = statementResponse . errorCode ?? "" ;
201+ const normalizedError = statementResponse . error . toLowerCase ( ) ;
202+ const isTransient =
203+ FlexQueryClient . TRANSIENT_GET_STATEMENT_ERROR_CODES . has ( code ) ||
204+ normalizedError . includes ( "in progress" ) ||
205+ normalizedError . includes ( "not ready" ) ||
206+ normalizedError . includes ( "try again" ) ;
207+
208+ if ( isTransient ) {
209+ Logger . log (
210+ `[FLEX-QUERY] Statement not ready yet (code ${ code || "?" } : ${ statementResponse . error } ), retrying...`
211+ ) ;
192212 continue ;
193213 }
194-
214+
195215 // It's a real error
196216 return statementResponse ;
197217 }
@@ -226,4 +246,3 @@ export class FlexQueryClient {
226246}
227247
228248
229-
0 commit comments