virattt/ai-hedge-fund · error · FDClientError
{method} {path} failed: {exc}
Error message
{method} {path} failed: {exc} What it means
Raised by FDClient._request (hedge_fund/data/client.py:277) when the underlying HTTP request raises a requests.RequestException — connection errors, DNS failures, TLS errors, timeouts. It is wrapped in FDClientError so the backtest pipeline sees one infrastructure-error type; per that class's docstring, a backtest must crash on this rather than treat it as 'no data'.
Source
Thrown at hedge_fund/data/client.py:277
"""HTTP request with retry on 429.
Fail-loud contract: raises FDClientError on network errors, HTTP
errors, and exhausted rate-limit retries. Returns None ONLY for
404 — "this data doesn't exist" is a data fact, not a failure.
Silently returning empty on real failures poisons backtests
(missing data reads as "no signal").
*path* may be an absolute URL (a ``next_page_url`` from a previous
response), which is requested verbatim.
"""
url = path if path.startswith("http") else self.BASE_URL + path
for attempt, delay in enumerate((*self._RETRY_DELAYS, None)):
try:
resp = self._session.request(
method, url, timeout=self._timeout, **kwargs,
)
except requests.RequestException as exc:
raise FDClientError(
f"{method} {path} failed: {exc}", path=path,
) from exc
if resp.status_code == 429 and delay is not None:
logger.info(
"Rate limited (429), retrying in %ds (attempt %d/%d)",
delay, attempt + 1, len(self._RETRY_DELAYS),
)
time.sleep(delay)
continue
if resp.status_code == 404:
return None
if resp.status_code >= 400:
raise FDClientError(
f"{method} {path} returned {resp.status_code}: {resp.text[:200]}",
status_code=resp.status_code, path=path,View on GitHub (pinned to eff8a7320f)
Solutions
- Check basic connectivity to the provider host (curl or a single minimal get_prices call) — if offline/VPN-blocked, fix the network first.
- If the exception mentions timeout, raise the client's timeout (FDClient(timeout=...)) or request a smaller date range per call.
- If behind a corporate proxy, configure HTTPS_PROXY/REQUESTS_CA_BUNDLE in the environment so requests can complete the TLS handshake.
- In orchestration code, catch FDClientError and retry the whole backtest after a delay — the client itself only retries 429s, not network errors.
Example fix
# before
bars = client.get_prices("SPY", "2020-01-01", "2024-12-31") # large range, times out -> FDClientError: GET ... failed: ReadTimeout
# after
client = FDClient(timeout=60)
bars = client.get_prices("SPY", "2020-01-01", "2024-12-31") Defensive patterns
Strategy: retry
Validate before calling
import socket
from urllib.parse import urlparse
def endpoint_reachable(base_url: str, timeout: float = 3.0) -> bool:
"""Cheap pre-flight: can we resolve+connect to the API host?"""
u = urlparse(base_url)
host, port = u.hostname, u.port or (443 if u.scheme == "https" else 80)
try:
with socket.create_connection((host, port), timeout=timeout):
return True
except OSError:
return False Type guard
from hedge_fund.data.client import FDClientError
def is_network_failure(e: FDClientError) -> bool:
"""Network-transport failure (no status_code) vs an HTTP error response."""
return isinstance(e, FDClientError) and e.status_code is None Try / catch
from hedge_fund.data.client import FDClientError
import time
def get_with_retry(fn, *args, tries=3, delay=10, **kwargs):
for i in range(tries):
try:
return fn(*args, **kwargs)
except FDClientError as e:
if e.status_code is not None or i == tries - 1:
raise # HTTP-level error or last try: propagate
time.sleep(delay * (i + 1)) Prevention
- Wrap the whole backtest in one FDClientError catch that distinguishes status_code None (network) from >=400 (HTTP).
- Pre-flight connectivity to the provider host before kicking off hour-long runs.
- Set a realistic FDClient timeout for large historical ranges; the default may be tuned to small requests.
When it happens
Trigger: Any FDClient API call (get_prices, get_financial_metrics, get_company_facts, ...) while offline; the data provider host is unreachable (DNS failure, firewall, VPN down); the request exceeds the client's configured timeout; a proxy or TLS interception breaks the connection. Note this branch does NOT retry — network exceptions fail on the first attempt; only HTTP 429s are retried.
Common situations: Running a backtest without network access; corporate proxy/MITM certificate rejecting the API host; too-aggressive timeout on a large historical range request; transient ISP/DNS outage mid-run. Also absolute next_page_url pagination calls failing when the provider domain changed.
Related errors
- {method} {path} returned {resp.status_code}: {resp.text[:200
- {method} {path} rate limited (429) after {len(self._RETRY_DE
AI-assisted analysis of virattt/ai-hedge-fund@eff8a7320f (2026-08-15).
Data as JSON: /api/errors/2423754ada3def92.
Report an issue: GitHub.