HKUDS/Vibe-Trading · warning · EtoroAPIError

mode must be 'auto', 'symbol', 'discover', or 'type'

Error message

mode must be 'auto', 'symbol', 'discover', or 'type'

What it means

Raised by search_instruments when the mode argument is not one of 'auto', 'symbol', 'discover', or 'type' (case-insensitive after strip/lower).

Source

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

            ``discover`` (fuzzy ``search`` param only), or ``type`` (browse by
            ``instrument_type_id`` / asset-class alias).
        instrument_type_id: Optional eToro ``instrumentTypeID`` filter (e.g. ``10``
            for crypto). When set, uses ``GET /market-data/instruments`` with
            ``instrumentTypeIds``.
        include_rates: When browsing by type, attach bid/ask/last from the flat
            ``/market-data/instruments/rates`` endpoint (works on all profiles).
    """
    from src.trading.connectors.etoro.client import load_config

    cfg = config or load_config()
    token = str(query or "").strip()
    if not token:
        raise EtoroAPIError("search query is required")

    clean_limit = max(1, min(int(limit), 50))
    clean_mode = str(mode or "auto").strip().lower()
    if clean_mode not in ("auto", "symbol", "discover", "type"):
        raise EtoroAPIError("mode must be 'auto', 'symbol', 'discover', or 'type'")

    if clean_mode == "type" or instrument_type_id is not None:
        resolved_type_id = instrument_type_id
        if resolved_type_id is None:
            resolved_type_id = _instrument_type_id_from_query(token, cfg)
        if resolved_type_id is None:
            raise EtoroAPIError(
                "instrument_type_id is required for type browse "
                "(e.g. 10 for crypto) or use an asset-class query like 'crypto'"
            )
        return list_instruments_by_type(
            resolved_type_id,
            cfg,
            limit=clean_limit,
            include_rates=include_rates,
        )

    rows: list[dict[str, Any]] = []

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Use exactly one of 'auto', 'symbol', 'discover', 'type'
  2. If mode comes from user input, validate against the allowed set before calling

Example fix

# before
search_instruments('btc', mode='ticker')
# after
search_instruments('btc', mode='symbol')
Defensive patterns

Strategy: validation

Validate before calling

VALID_MODES = {'auto', 'symbol', 'discover', 'type'}
mode = (mode or 'auto').strip().lower()
assert mode in VALID_MODES, f'mode must be one of {VALID_MODES}'

Type guard

def is_valid_mode(mode: str | None) -> bool:
    return (mode or 'auto').strip().lower() in {'auto','symbol','discover','type'}

Prevention

When it happens

Trigger: Calling search_instruments('btc', mode='tick') or mode='symbol-match' or any typo like 'Auto ' handled fine but 'aauto' not.

Common situations: Typos in mode strings, outdated mode names after a library upgrade, dynamic mode built from user input.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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