TauricResearch/TradingAgents · error · ValueError

FRED request failed: {message}

Error message

FRED request failed: {message}

What it means

Raised by _request() in tradingagents/dataflows/fred.py when the FRED API answers HTTP 400 with a JSON body; the JSON's error_message (or raw text if the body isn't JSON) is embedded so the failure is actionable. It is a plain ValueError, so the router's generic handler records it as the first_error and it propagates only if no other configured vendor succeeds.

Source

Thrown at tradingagents/dataflows/fred.py:131

            f"FRED series ID (e.g. 'CPIAUCSL')."
        )
    return candidate


def _request(path: str, params: dict) -> dict:
    """GET a FRED endpoint, surfacing FRED's JSON error body on a bad request."""
    api_params = {**params, "api_key": get_api_key(), "file_type": "json"}
    response = requests.get(
        f"{FRED_API_BASE}/{path}", params=api_params, timeout=REQUEST_TIMEOUT
    )
    # FRED returns 400 with a JSON {"error_message": ...} for unknown series IDs
    # or malformed params; turn that into a clear, actionable error.
    if response.status_code == 400:
        try:
            message = response.json().get("error_message", response.text)
        except ValueError:
            message = response.text
        raise ValueError(f"FRED request failed: {message}")
    response.raise_for_status()
    return response.json()


def get_macro_data(
    indicator: str,
    curr_date: str,
    look_back_days: int | None = None,
) -> str:
    """Fetch a FRED macroeconomic series as a formatted markdown report.

    Args:
        indicator: A friendly alias (e.g. "cpi", "unemployment", "10y_treasury")
            or a raw FRED series ID (e.g. "CPIAUCSL", "DGS10").
        curr_date: End of the window (yyyy-mm-dd); no later observations are
            returned, so a past date never leaks future data.
        look_back_days: Trailing window length; ``None`` uses DEFAULT_LOOKBACK_DAYS.

View on GitHub (pinned to a33fd4c0f1)

Solutions

  1. Read the embedded message — FRED states the exact problem (e.g. 'The series does not exist')
  2. Validate the series ID first via FRED's search: curl 'https://api.stlouisfed.org/fred/series/search?search_text=...&api_key=...&file_type=json'
  3. Prefer documented aliases (MACRO_SERIES) over hand-typed IDs
  4. Wrap the call in try/except ValueError to degrade gracefully (report unavailable macro data) rather than aborting the run

Example fix

# before
get_macro_data("NOT_A_SERIES", "2025-06-10")
# -> ValueError: FRED request failed: The series 'NOT_A_SERIES' does not exist...

# after
try:
    report = get_macro_data("CPIAUCSL", "2025-06-10")
except ValueError as e:
    report = f"Macro data unavailable: {e}"  # degrade instead of crash
Defensive patterns

Strategy: try-catch

Validate before calling

import requests, os

def fred_series_exists(series_id: str) -> bool:
    r = requests.get("https://api.stlouisfed.org/fred/series", params={
        "series_id": series_id, "api_key": os.environ["FRED_API_KEY"], "file_type": "json"}, timeout=15)
    return r.ok and r.json().get("seriess")

Try / catch

try:
    report = get_macro_data(series, curr_date)
except ValueError as e:
    if str(e).startswith("FRED request failed:"):
        report = f"Macro series {series} unavailable ({e})"  # log & degrade; do not blindly retry a 400
    else:
        raise

Prevention

When it happens

Trigger: Requesting a series ID that does not exist (e.g. 'CPIAUCSL' typo'd as 'CPIAUCS'), malformed parameters, or an invalid API key value that FRED rejects at the parameter level. Note: a *missing* key raises FredNotConfiguredError earlier; a syntactically bad request gets this 400 error.

Common situations: LLM-constructed or user-supplied series IDs that look valid but aren't; stale series IDs discontinued by FRED; passing wrong parameter names for observation endpoints; keys with whitespace causing auth failure at FRED's edge.

Related errors


AI-assisted analysis of TauricResearch/TradingAgents@a33fd4c0f1 (2026-08-14). Data as JSON: /api/errors/f1ab6e291c6a16c5. Report an issue: GitHub.