HKUDS/Vibe-Trading · error · EtoroAPIError

instrument not found for symbol

Error message

instrument not found for symbol {token!r}

What it means

Raised by resolve_instrument_id when no lookup variant of the symbol (raw, canonical ticker, alias variants) matched any instrument with positive match priority. The ticker is unknown to eToro.

Solutions

  1. Verify the ticker with search_instruments(symbol) first
  2. Try common variants (drop suffixes like '-USD', remove dots)
  3. Check the asset is actually listed on eToro

Example fix

# before
resolve_instrument_id('BTC-USD')
# after
matches = search_instruments('BTC-USD', mode='symbol')
resolve_instrument_id(str(matches[0]['instrumentId']))
Defensive patterns

Strategy: fallback

Validate before calling

matches = search_instruments(symbol, mode='symbol') or search_instruments(symbol, mode='discover')
if not matches:
    raise ValueError(f'{symbol} not listed on eToro')

Try / catch

try:
    iid = resolve_instrument_id(symbol)
except EtoroAPIError as exc:
    if 'not found' in str(exc):
        suggestions = search_instruments(symbol, mode='discover')
        # offer suggestions or fail gracefully
    raise

Prevention

When it happens

Trigger: resolve_instrument_id('XYZZY') for a ticker eToro doesn't list; delisted symbols; wrong exchange suffix; misspelled ticker passed to get_quote or place_order.

Common situations: Delisted or renamed tickers, OTC symbols not on eToro, user typos, symbols formatted like 'BTC-USD' when eToro expects 'BTCUSD'.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/2598d92dd755f33a. Report an issue: GitHub.

Appendix: source

Thrown at agent/src/trading/connectors/etoro/instruments.py:328

        for item in _search_by_symbol(cfg, lookup, limit=25):
            instrument_id = _instrument_id(item)
            if instrument_id is None:
                continue
            priority = _match_priority(item, lookup, canonical, token)
            if priority > 0:
                candidates.append((priority, instrument_id))

    if not candidates:
        for item in _search_by_text(cfg, canonical, limit=25):
            instrument_id = _instrument_id(item)
            if instrument_id is None:
                continue
            priority = _match_priority(item, canonical, canonical, token)
            if priority > 0:
                candidates.append((priority, instrument_id))

    if not candidates:
        raise EtoroAPIError(f"instrument not found for symbol {token!r}")

    candidates.sort(key=lambda pair: (-pair[0], pair[1]))
    return candidates[0][1]


def get_instrument_metadata(
    instrument_ids: list[int] | tuple[int, ...],
    config: EtoroConfig | None = None,
) -> dict[str, Any]:
    """Fetch display metadata for one or more instrument ids (batch ≤ 50)."""
    from src.trading.connectors.etoro.client import load_config

    cfg = config or load_config()
    ids = [int(i) for i in instrument_ids if int(i) not in _INVALID_INSTRUMENT_IDS and int(i) > 0]
    if not ids:
        raise EtoroAPIError("at least one valid instrument_id is required")
    if len(ids) > 50:
        raise EtoroAPIError("instrumentIds batch limit is 50")

View on GitHub (pinned to 80ffdda44c)