{"record":{"id":"b1065518ec450bc2","repo":"HKUDS/Vibe-Trading","slug":"too-many-symbols-len-symbols-cap-is-max-sy","errorCode":null,"errorMessage":"too many symbols ({len(symbols)}); cap is {_MAX_SYMBOLS}","messagePattern":"too many symbols \\((.+?)\\); cap is (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/portfolio_risk_tool.py","lineNumber":102,"sourceCode":"    def execute(self, **kwargs: Any) -> str:\n        try:\n            return self._run(**kwargs)\n        except Exception as exc:  # noqa: BLE001 — tool must always return JSON\n            logger.warning(\"portfolio_risk_xray failed: %s\", exc)\n            return json.dumps(\n                {\"status\": \"error\", \"error\": str(exc)}, ensure_ascii=False, allow_nan=False\n            )\n\n    # ------------------------------------------------------------------\n    def _run(self, **kwargs: Any) -> str:\n        symbols = kwargs.get(\"symbols\")\n        if not isinstance(symbols, list) or not symbols or not all(\n            isinstance(s, str) and s.strip() for s in symbols\n        ):\n            raise ValueError(\"symbols must be a non-empty list of strings\")\n        symbols = [s.strip() for s in symbols]\n        if len(symbols) > _MAX_SYMBOLS:\n            raise ValueError(f\"too many symbols ({len(symbols)}); cap is {_MAX_SYMBOLS}\")\n\n        weights = self._parse_weights(kwargs.get(\"weights\"), symbols)\n        start_date, end_date = self._parse_dates(kwargs.get(\"start_date\"), kwargs.get(\"end_date\"))\n        source = str(kwargs.get(\"source\") or \"auto\")\n        interval = str(kwargs.get(\"interval\") or \"1D\")\n\n        raw = self._fetch(\n            codes=symbols,\n            start_date=start_date,\n            end_date=end_date,\n            source=source,\n            interval=interval,\n        )\n        closes = self._closes_frame(raw, symbols)\n        unresolved = raw.get(\"_unresolved\") if isinstance(raw, Mapping) else None\n\n        report = compute_risk_xray(closes, weights)\n        envelope = {","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/portfolio_risk_tool.py#L84-L120","documentation":"After symbol validation, _run enforces the basket size cap _MAX_SYMBOLS; exceeding it raises with the actual count and the cap value so the caller knows how much to trim.","triggerScenarios":"Passing more than _MAX_SYMBOLS symbols, e.g. an entire index constituent list.","commonSituations":"Backtesting whole universes instead of baskets, unioning watchlists, or LLMs pasting long ticker lists.","solutions":["Trim to the cap (prioritize highest-conviction/highest-liquidity names)","Batch into multiple calls and aggregate results if supported","Read the cap from the error message or module constant"],"exampleFix":"# before\nexecute(symbols=all_500_tickers)\n# after\nexecute(symbols=all_500_tickers[:_MAX_SYMBOLS])","handlingStrategy":"validation","validationCode":"from agent.src.tools.portfolio_risk_tool import _MAX_SYMBOLS\nif len(symbols) > _MAX_SYMBOLS:\n    symbols = symbols[:_MAX_SYMBOLS]  # or batch","typeGuard":"def within_symbol_cap(syms: list[str], cap: int) -> bool:\n    return len(syms) <= cap","tryCatchPattern":"try:\n    out = tool.execute(symbols=symbols)\nexcept ValueError as e:\n    if \"cap is\" in str(e):\n        out = tool.execute(symbols=symbols[:_MAX_SYMBOLS])","preventionTips":["Trim watchlists before analysis","Batch large universes into multiple calls","Read the cap from the error message or module constant"],"tags":["portfolio-risk","limit","symbols"],"backgroundTag":"resource-limit-exceeded","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}