{"record":{"id":"e53d81894293ad4f","repo":"HKUDS/Vibe-Trading","slug":"at-least-one-valid-instrument-id-is-required","errorCode":null,"errorMessage":"at least one valid instrument_id is required","messagePattern":"at least one valid instrument_id is required","errorType":"validation","errorClass":"EtoroAPIError","httpStatus":null,"severity":"warning","filePath":"agent/src/trading/connectors/etoro/instruments.py","lineNumber":344,"sourceCode":"\n    if not candidates:\n        raise EtoroAPIError(f\"instrument not found for symbol {token!r}\")\n\n    candidates.sort(key=lambda pair: (-pair[0], pair[1]))\n    return candidates[0][1]\n\n\ndef get_instrument_metadata(\n    instrument_ids: list[int] | tuple[int, ...],\n    config: EtoroConfig | None = None,\n) -> dict[str, Any]:\n    \"\"\"Fetch display metadata for one or more instrument ids (batch ≤ 50).\"\"\"\n    from src.trading.connectors.etoro.client import load_config\n\n    cfg = config or load_config()\n    ids = [int(i) for i in instrument_ids if int(i) not in _INVALID_INSTRUMENT_IDS and int(i) > 0]\n    if not ids:\n        raise EtoroAPIError(\"at least one valid instrument_id is required\")\n    if len(ids) > 50:\n        raise EtoroAPIError(\"instrumentIds batch limit is 50\")\n\n    payload = make_client(cfg).request(\n        \"GET\",\n        MARKET_DATA_INSTRUMENTS_PATH,\n        params={\"instrumentIds\": \",\".join(str(i) for i in ids)},\n        allow_retry=True,\n    )\n    items = _extract_metadata_items(payload)\n    instruments = [_normalize_metadata_row(item) for item in items if isinstance(item, dict)]\n    return {\"status\": \"ok\", **_base_payload(cfg), \"instruments\": instruments}\n\n\ndef _canonical_ticker(token: str) -> str:\n    upper = token.strip().upper()\n    return _SYMBOL_ALIASES.get(upper, upper)\n","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/etoro/instruments.py#L326-L362","documentation":"Raised by get_instrument_metadata when, after filtering out invalid/non-positive ids, no ids remain to request.","triggerScenarios":"get_instrument_metadata([]), or passing only ids like 0 or negatives; downstream _enrich_positions_with_metadata with positions whose ids all filter out.","commonSituations":"Empty positions list passed for enrichment; data quality issue where all instrument ids are 0/missing.","solutions":["Check the id list is non-empty and contains positive ints before calling","Fix upstream data producing 0/None instrument ids"],"exampleFix":"# before\nget_instrument_metadata([0, -1])\n# after\nids = [i for i in raw_ids if isinstance(i, int) and i > 0]\nif ids:\n    get_instrument_metadata(ids)","handlingStrategy":"validation","validationCode":"ids = [i for i in raw_ids if int(i) > 0 and int(i) not in _INVALID_INSTRUMENT_IDS]\nif not ids:\n    return {}  # nothing to enrich","typeGuard":"def valid_metadata_ids(ids: list[int]) -> list[int]:\n    return [i for i in ids if i > 0][:50]","tryCatchPattern":null,"preventionTips":["Filter and dedupe id lists before batch metadata calls","Skip enrichment when positions carry no valid instrument id"],"tags":["etoro","metadata","validation"],"backgroundTag":"missing-required-parameter","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}