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).

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.

Appendix: 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)