HKUDS/Vibe-Trading · warning · EtoroAPIError

invalid instrument id {instrument_id}

Error message

invalid instrument id {instrument_id}

What it means

Raised by resolve_instrument_id when the input is all digits but the resulting integer is negative or in the _INVALID_INSTRUMENT_IDS blocklist (known non-tradeable placeholder ids like 0).

Source

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

    return {
        "status": "ok",
        **_base_payload(cfg),
        "instrument_type_id": type_id,
        "instrument_type": id_to_label[type_id],
        "mode": "type",
        "instruments": instruments,
    }


def resolve_instrument_id(symbol: str, cfg: EtoroConfig) -> int:
    """Resolve a user symbol to an eToro ``instrumentId`` for trading APIs."""
    token = str(symbol or "").strip()
    if not token:
        raise EtoroAPIError("symbol is required")
    if token.isdigit():
        instrument_id = int(token)
        if instrument_id in _INVALID_INSTRUMENT_IDS or instrument_id < 0:
            raise EtoroAPIError(f"invalid instrument id {instrument_id}")
        return instrument_id

    canonical = _canonical_ticker(token)
    candidates: list[tuple[int, int]] = []  # (priority, instrument_id)

    for lookup in _lookup_variants(token, canonical):
        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:

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use a real positive instrument id from search_instruments or get_instrument_metadata
  2. Guard against 0/placeholder ids in your data pipeline

Example fix

# before
resolve_instrument_id('0')
# after
resolve_instrument_id(str(search_instruments('BTC')[0]['instrumentId']))
Defensive patterns

Strategy: validation

Validate before calling

INVALID = {0}
if sym.strip().lstrip('-').isdigit():
    val = int(sym)
    if val < 0 or val in INVALID:
        raise ValueError(f'placeholder instrument id {val}')

Type guard

def is_valid_instrument_id(value: int) -> bool:
    return value > 0 and value not in _INVALID_INSTRUMENT_IDS

Prevention

When it happens

Trigger: resolve_instrument_id('0'), resolve_instrument_id('-5') after strip of a numeric string in the blocklist; get_quote('0').

Common situations: UI defaulting instrument id to 0; parsing a CSV where missing ids become 0; using placeholder ids from sample responses.

Related errors


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