{"record":{"id":"1055ca6b1372b4d0","repo":"HKUDS/Vibe-Trading","slug":"search-query-is-required","errorCode":null,"errorMessage":"search query is required","messagePattern":"search query is required","errorType":"validation","errorClass":"EtoroAPIError","httpStatus":null,"severity":"warning","filePath":"agent/src/trading/connectors/etoro/instruments.py","lineNumber":187,"sourceCode":"        query: Symbol (``BTC``, ``AAPL``), discovery text, or asset-class label\n            (``crypto``, ``stocks``, ``forex``).\n        config: Optional connector config.\n        limit: Max results (capped at 50).\n        mode: ``auto`` (ticker → exact lookup then fuzzy), ``symbol`` (exact only),\n            ``discover`` (fuzzy ``search`` param only), or ``type`` (browse by\n            ``instrument_type_id`` / asset-class alias).\n        instrument_type_id: Optional eToro ``instrumentTypeID`` filter (e.g. ``10``\n            for crypto). When set, uses ``GET /market-data/instruments`` with\n            ``instrumentTypeIds``.\n        include_rates: When browsing by type, attach bid/ask/last from the flat\n            ``/market-data/instruments/rates`` endpoint (works on all profiles).\n    \"\"\"\n    from src.trading.connectors.etoro.client import load_config\n\n    cfg = config or load_config()\n    token = str(query or \"\").strip()\n    if not token:\n        raise EtoroAPIError(\"search query is required\")\n\n    clean_limit = max(1, min(int(limit), 50))\n    clean_mode = str(mode or \"auto\").strip().lower()\n    if clean_mode not in (\"auto\", \"symbol\", \"discover\", \"type\"):\n        raise EtoroAPIError(\"mode must be 'auto', 'symbol', 'discover', or 'type'\")\n\n    if clean_mode == \"type\" or instrument_type_id is not None:\n        resolved_type_id = instrument_type_id\n        if resolved_type_id is None:\n            resolved_type_id = _instrument_type_id_from_query(token, cfg)\n        if resolved_type_id is None:\n            raise EtoroAPIError(\n                \"instrument_type_id is required for type browse \"\n                \"(e.g. 10 for crypto) or use an asset-class query like 'crypto'\"\n            )\n        return list_instruments_by_type(\n            resolved_type_id,\n            cfg,","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/trading/connectors/etoro/instruments.py#L169-L205","documentation":"Raised by search_instruments when the query string, after stripping, is empty. The search API requires a non-empty token.","triggerScenarios":"Calling search_instruments(''), search_instruments(None), or with a whitespace-only query.","commonSituations":"UI passing an empty search box value; default parameter of '' flowing through; f-string building a query from a missing variable.","solutions":["Validate the query is non-empty before calling search_instruments","Default the caller's input (e.g. require at least one character in the UI)"],"exampleFix":"# before\nresults = search_instruments(user_query)  # user_query may be ''\n# after\ntoken = (user_query or '').strip()\nif not token:\n    raise ValueError('enter a search term')\nresults = search_instruments(token)","handlingStrategy":"validation","validationCode":"token = (query or '').strip()\nif not token:\n    # skip the call; show 'enter a search term' in UI\n    return []","typeGuard":"def is_valid_search_query(q: str | None) -> bool:\n    return bool(q and q.strip())","tryCatchPattern":null,"preventionTips":["Require non-empty input in UI before triggering search","Strip and check query strings at the boundary of your app"],"tags":["etoro","validation","search"],"backgroundTag":"missing-required-parameter","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}