{"record":{"id":"01332bd39b66a16e","repo":"we-promise/sure","slug":"network-error-after-max-retries-retries-e-me","errorCode":null,"errorMessage":"Network error after #{max_retries} retries: #{e.message}","messagePattern":"Network error after #(.+?) retries: #(.+?)","errorType":"exception","errorClass":"ApiError","httpStatus":null,"severity":"error","filePath":"app/models/provider/ibkr_flex.rb","lineNumber":135,"sourceCode":"\n    def with_retries(operation_name, max_retries: MAX_RETRIES)\n      retries = 0\n\n      begin\n        yield\n      rescue *RETRYABLE_ERRORS => e\n        retries += 1\n\n        if retries <= max_retries\n          delay = calculate_retry_delay(retries)\n          Rails.logger.warn(\n            \"IBKR Flex: #{operation_name} failed (attempt #{retries}/#{max_retries}): #{e.class}: #{e.message}. Retrying in #{delay}s...\"\n          )\n          sleep(delay)\n          retry\n        end\n\n        raise ApiError.new(\"Network error after #{max_retries} retries: #{e.message}\")\n      end\n    end\n\n    def calculate_retry_delay(retry_count)\n      base_delay = INITIAL_RETRY_DELAY * (2**(retry_count - 1))\n      jitter = base_delay * rand * 0.25\n      [ base_delay + jitter, MAX_RETRY_DELAY ].min\n    end\nend\n","sourceCodeStart":117,"sourceCodeEnd":145,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/ibkr_flex.rb#L117-L145","documentation":"with_retries ran the SendRequest or GetStatement call MAX_RETRIES=3 times with exponential backoff (2s base, doubling, capped 30s, +25% jitter) and every attempt raised a transport error from RETRYABLE_ERRORS: SocketError, Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNRESET, Errno::ECONNREFUSED, Errno::ETIMEDOUT or EOFError against ndcdyn.interactivebrokers.com.","triggerScenarios":"DNS cannot resolve ndcdyn.interactivebrokers.com; egress firewall/proxy blocks HTTPS to IBKR; connection resets from an intermediary (SSL inspection); a single GetStatement hanging past the 120s HTTParty timeout three times in a row; local network outage during a sync job.","commonSituations":"Corporate/容器ized environments without outbound allowlist entries for IBKR, transient ISP or IBKR edge failures lasting longer than ~14s of cumulative backoff, runs scheduled during IBKR maintenance windows.","solutions":["Verify connectivity from the same host: curl -v https://ndcdyn.interactivebrokers.com/AccountManagement/FlexWebService/SendRequest - a TLS handshake proves DNS, routing and firewall are fine","Check DNS and proxy settings for the process (resolv.conf, HTTP_PROXY/http_proxy env leaking into HTTParty)","Reschedule the sync - this error means the transport layer is down, so let the scheduler retry on the next cycle instead of retrying inline","If only ReadTimeouts, the statement may be genuinely huge; shrink the Flex Query date range"],"exampleFix":"# before\nflex.download_statement rescue nil # silent drop\n\n# after\nbegin\n  flex.download_statement\nrescue Provider::IbkrFlex::ApiError => e\n  SyncFailure.record!(account, provider: :ibkr_flex, reason: e.message, retry_at: 1.hour.from_now)\nend","handlingStrategy":"retry","validationCode":"# cheap pre-flight before a sync run (fail fast instead of ~14s of provider backoff)\nrequire \"socket\"\ndef ibkr_reachable?(timeout: 3)\n  TCPSocket.new(\"ndcdyn.interactivebrokers.com\", 443, connect_timeout: timeout).close\n  true\nrescue SocketError, Errno::ECONNREFUSED, Errno::ETIMEDOUT, IO::TimeoutError\n  false\nend","typeGuard":"def ibkr_network_exhausted?(error)\n  error.is_a?(Provider::IbkrFlex::ApiError) && error.message.start_with?(\"Network error after\")\nend","tryCatchPattern":"begin\n  flex.download_statement\nrescue Provider::IbkrFlex::ApiError => e\n  raise unless e.message.start_with?(\"Network error after\")\n  SyncFailure.record!(account, provider: :ibkr_flex,\n    reason: e.message, retry_at: 1.hour.from_now) # transport down; try next cycle\nend","preventionTips":["Allowlist ndcdyn.interactivebrokers.com:443 in egress firewalls for every app host","Add a connectivity pre-flight in deploy checks so config drift is caught early","Hand network-exhausted errors to the scheduler instead of inline retry loops (the provider already retried 3x)","Watch for proxy env vars (HTTP_PROXY) leaking into HTTParty"],"tags":["ibkr-flex","network","retries-exhausted","dns","firewall","transport"],"backgroundTag":"connection-failed-after-retries","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}