TauricResearch/TradingAgents · error · ValueError

llm_max_retries must be an integer, not a boolean: {value!r}

Error message

llm_max_retries must be an integer, not a boolean: {value!r}

What it means

ValueError raised by _coerce_max_retries (tradingagents/graph/trading_graph.py) when the llm_max_retries value is a bool. In Python, bool is a subclass of int, so True would silently coerce to 1 retry — the explicit isinstance(value, bool) check rejects it so a misconfiguration like llm_max_retries=True fails at startup rather than half-working.

Source

Thrown at tradingagents/graph/trading_graph.py:55

from .checkpointer import checkpoint_step, clear_checkpoint, get_checkpointer, thread_id
from .conditional_logic import ConditionalLogic
from .propagation import Propagator
from .reflection import Reflector
from .setup import GraphSetup
from .signal_processing import SignalProcessor

logger = logging.getLogger(__name__)


def _coerce_max_retries(value):
    """Validate an ``llm_max_retries`` value to a non-negative int.

    Accepts an int or a numeric string (env vars arrive as strings). Rejects
    booleans and negatives loudly so a misconfiguration fails at startup rather
    than silently disabling retries.
    """
    if isinstance(value, bool):
        raise ValueError(f"llm_max_retries must be an integer, not a boolean: {value!r}")
    try:
        n = int(value)
    except (TypeError, ValueError) as exc:
        raise ValueError(f"llm_max_retries must be an integer, got {value!r}") from exc
    if n < 0:
        raise ValueError(f"llm_max_retries must be >= 0, got {n}")
    return n


class TradingAgentsGraph:
    """Main class that orchestrates the trading agents framework."""

    def __init__(
        self,
        selected_analysts=("market", "social", "news", "fundamentals"),
        debug=False,
        config: dict[str, Any] = None,
        callbacks: list | None = None,

View on GitHub (pinned to a33fd4c0f1)

Solutions

  1. Set llm_max_retries to a non-negative integer, e.g. 3 (or the string '3' from env vars).
  2. Fix YAML/JSON config files that define the value as true/false.
  3. Audit any config preprocessing that coerces values to bool before they reach the graph.

Example fix

# before
TradingAgentsGraph(config={**DEFAULT_CONFIG, 'llm_max_retries': True})

# after
TradingAgentsGraph(config={**DEFAULT_CONFIG, 'llm_max_retries': 3})
Defensive patterns

Strategy: type-guard

Validate before calling

def is_valid_max_retries(value) -> bool:
    return not isinstance(value, bool) and isinstance(value, (int, str)) and str(value).lstrip('-').isdigit()

Type guard

def isNonNegativeIntLike(value: unknown): value is number | string {
  return (typeof value === 'number' || typeof value === 'string')
    && /^\d+$/.test(String(value).trim());
}

Try / catch

try:
    graph = TradingAgentsGraph(config=config)
except ValueError as e:
    if 'llm_max_retries' in str(e):
        config['llm_max_retries'] = 3
        graph = TradingAgentsGraph(config=config)
    else:
        raise

Prevention

When it happens

Trigger: Passing llm_max_retries=True or False to TradingAgentsGraph, or setting a TRADINGAGENTS_* env var / config value that a previous layer converted to a boolean. The bool check fires before int() conversion.

Common situations: Config templating that turns numeric strings into booleans ('1' -> True); YAML files where `llm_max_retries: true` is accepted as a bool; users intending 'on/off' semantics for a count parameter.

Related errors


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