{"record":{"id":"4919d8d197311291","repo":"TauricResearch/TradingAgents","slug":"at-least-one-analyst-must-be-selected","errorCode":null,"errorMessage":"at least one analyst must be selected","messagePattern":"at least one analyst must be selected","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"tradingagents/graph/analyst_execution.py","lineNumber":67,"sourceCode":"        clear_node=\"Msg Clear Fundamentals\",\n        tool_node=\"tools_fundamentals\",\n        report_key=\"fundamentals_report\",\n    ),\n}\n\n\ndef build_analyst_execution_plan(\n    selected_analysts: Iterable[str],\n) -> AnalystExecutionPlan:\n    specs: list[AnalystNodeSpec] = []\n    for analyst_key in selected_analysts:\n        spec = ANALYST_NODE_SPECS.get(analyst_key)\n        if spec is None:\n            raise ValueError(f\"unknown analyst key: {analyst_key}\")\n        specs.append(spec)\n\n    if not specs:\n        raise ValueError(\"at least one analyst must be selected\")\n\n    return AnalystExecutionPlan(specs=specs)\n\n\ndef get_initial_analyst_node(plan: AnalystExecutionPlan) -> str:\n    return plan.specs[0].agent_node\n\n\nclass AnalystWallTimeTracker:\n    def __init__(self, plan: AnalystExecutionPlan):\n        self.plan = plan\n        self._started_at: dict[str, float] = {}\n        self._wall_times: dict[str, float] = {}\n\n    def mark_started(self, analyst_key: str, started_at: float | None = None) -> None:\n        if analyst_key not in ANALYST_NODE_SPECS:\n            raise ValueError(f\"unknown analyst key: {analyst_key}\")\n        self._started_at.setdefault(analyst_key, monotonic() if started_at is None else started_at)","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/TauricResearch/TradingAgents/blob/a33fd4c0f134485a43553a2c23a63cb14adbd88f/tradingagents/graph/analyst_execution.py#L49-L85","documentation":"ValueError raised by build_analyst_execution_plan when the selected_analysts iterable is empty — the graph has no analyst nodes to execute. It is a startup sanity check: an execution plan with zero specs is meaningless, so construction fails fast with a clear message.","triggerScenarios":"Passing selected_analysts=() or [] (or an iterable that yields only entries later filtered out upstream) to TradingAgentsGraph / build_analyst_execution_plan. Also passing None-like empty collections from config, e.g. an empty YAML list under selected_analysts.","commonSituations":"Config-driven deployments where the analysts list is conditionally emptied; filters that remove all analysts; defaulting to an empty list when the config key is missing.","solutions":["Ensure at least one valid analyst key is selected, e.g. ('market',).","Fix config loading so a missing 'selected_analysts' key falls back to the full default set, not an empty list.","Validate the config at startup before constructing TradingAgentsGraph."],"exampleFix":"# before\nTradingAgentsGraph(selected_analysts=[])\n\n# after\nTradingAgentsGraph(selected_analysts=('market', 'social', 'news', 'fundamentals'))","handlingStrategy":"validation","validationCode":"DEFAULT_ANALYSTS = ('market', 'social', 'news', 'fundamentals')\n\ndef resolve_analysts(cfg: dict):\n    selected = cfg.get('selected_analysts') or DEFAULT_ANALYSTS  # never empty\n    return tuple(selected) if selected else DEFAULT_ANALYSTS","typeGuard":null,"tryCatchPattern":"try:\n    graph = TradingAgentsGraph(selected_analysts=selected)\nexcept ValueError as e:\n    if 'at least one analyst' in str(e):\n        graph = TradingAgentsGraph(selected_analysts=('market',))\n    else:\n        raise","preventionTips":["Never default a missing analysts config key to an empty list — default to the full set.","Assert non-emptiness in your config loader before constructing the graph.","Add a config schema check in CI for analyst selection."],"tags":["validation","configuration","analysts","graph"],"backgroundTag":null,"analyzedSha":"a33fd4c0f134485a43553a2c23a63cb14adbd88f","analyzedAt":"2026-08-14T19:45:16.920Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}