HKUDS/Vibe-Trading · error · BinanceConfigError

{exc}

Error message

{exc}

What it means

Raised when _get_usdm_observation wraps any UsdMObservationError from read_account_observation into BinanceConfigError via `raise BinanceConfigError(str(exc)) from None`. It is a re-translation at the SDK boundary: the underlying USD-M observation (account read, payload validation, or coherence check) failed, and the connector reports it as a configuration error. The `from None` suppresses the original traceback, so the message string is the only clue to the root cause.

Source

Thrown at agent/src/trading/connectors/binance/sdk.py:703

def _reject_unsupported_usdm_surface(cfg: BinanceConfig) -> None:
    if cfg.market_type == "usdm":
        raise BinanceConfigError(
            "Binance USD-M Shadow Account exposes account and position reads only"
        )


def _get_usdm_observation(cfg: BinanceConfig, exchange: Any) -> dict[str, Any]:
    try:
        return read_account_observation(
            exchange,
            source_profile="binance-live-sdk-readonly",
            host=cfg.host,
            now=_utc_now,
            absolute_tolerance=cfg.observation_absolute_tolerance,
        )
    except UsdMObservationError as exc:
        raise BinanceConfigError(str(exc)) from None


def _exchange(cfg: BinanceConfig):
    """Build a ccxt Binance client bound to the configured market/environment."""
    ccxt = _require_ccxt()
    client_config: dict[str, Any] = {
        "apiKey": cfg.api_key,
        "secret": cfg.api_secret,
        "enableRateLimit": True,
        "timeout": int(cfg.timeout * 1000),
        # Signed Binance requests have a narrow timestamp window. Let ccxt
        # measure the exchange clock before the first private request so a
        # sleeping laptop or an imperfect system clock does not force users to
        # reconnect or recreate an otherwise valid read-only API key.
        "options": {
            "adjustForTimeDifference": True,
            "recvWindow": 10_000,
        },

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check the wrapped message text — it identifies which underlying UsdMObservationError fired (multi-asset margin, open-order margin, payload shape, or totals coherence) and fix that condition on the account/config
  2. Log/inspect the raw exchange.fapiprivatev2_get_account() and fapiprivatev3_get_positionrisk() responses to see which invariant broke
  3. Ensure observation_absolute_tolerance is a non-negative finite float in the config
  4. If the shadow-account invariants (no open orders, single-asset margin) are intentionally unsupported, route to a different snapshot code path or document the limitation

Example fix

# before
snapshot = sdk.get_account_snapshot(cfg)  # BinanceConfigError: multi-asset margin...

# after
try:
    snapshot = sdk.get_account_snapshot(cfg)
except BinanceConfigError as exc:
    logger.error("usdm observation failed: %s", exc)
    raise
# then disable multi-assets margin on the Binance futures account or set observation_absolute_tolerance >= 0
Defensive patterns

Strategy: try-catch

Validate before calling

# before calling: pre-verify the observation invariants cheaply
from trading.connectors.binance.usdm import read_account_observation
try:
    read_account_observation(ex, source_profile=cfg.profile, host=cfg.host, now=_utc_now,
                             absolute_tolerance=cfg.observation_absolute_tolerance)
except UsdMObservationError as e:
    logger.warning('usdm observation will fail: %s', e)

Type guard

def is_usdm_snapshot_ok(snapshot: object) -> bool:
    return isinstance(snapshot, Mapping) and all(
        isinstance(snapshot.get(k), (int, float)) for k in
        ('wallet_balance', 'margin_balance', 'available_balance'))

Try / catch

try:
    snapshot = sdk.get_account_snapshot(cfg)
except BinanceConfigError as exc:
    if 'observation' in str(exc) or 'USD-M' in str(exc):
        logger.error('usdm observation invariant violated: %s', exc)
        alert_ops(exc)
    raise

Prevention

When it happens

Trigger: Calling get_account_snapshot() or get_positions() on a usdm market_type config where read_account_observation raises UsdMObservationError: invalid tolerance settings, non-mapping account payload from fapiprivatev2_get_account(), non-list position risk from fapiprivatev3_get_positionrisk(), multi-asset margin enabled, non-zero open-order margin, or incoherent account vs USDT asset totals.

Common situations: Testnet/live account with multi-assets margin toggled on in Binance futures settings; existing open orders on the account (non-zero totalOpenOrderInitialMargin); API key permissions returning truncated payloads; misconfigured observation_absolute_tolerance (NaN or negative); ccxt version drift changing fapiprivate response shapes.

Related errors


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