HKUDS/Vibe-Trading · error · UsdMObservationError
Binance USD-M endpoint '{endpoint}' resolved to unapproved h
Error message
Binance USD-M endpoint '{endpoint}' resolved to unapproved host or path '{url}'. What it means
assert_exchange_endpoints validates each resolved USD-M endpoint URL: it must have an https scheme, hostname exactly fapi.binance.com, no port, a path equal (after rstrip('/')) to the expected path, and no query or fragment. Any deviation raises UsdMObservationError, which _exchange re-wraps as BinanceConfigError (error 1201's twin at the source). This is deliberate URL-pinning to block SSRF-style or accidental endpoint drift.
Source
Thrown at agent/src/trading/connectors/binance/usdm.py:49
"""Require exact HTTPS base URLs for the two signed USD-M reads."""
urls = getattr(exchange, "urls", None)
api_urls = urls.get("api") if isinstance(urls, Mapping) else None
expected_paths = {
"fapiPrivateV2": "/fapi/v2",
"fapiPrivateV3": "/fapi/v3",
}
for endpoint, expected_path in expected_paths.items():
url = str(api_urls.get(endpoint, "")) if isinstance(api_urls, Mapping) else ""
parsed = urlparse(url)
if (
parsed.scheme != "https"
or parsed.hostname != "fapi.binance.com"
or parsed.port is not None
or parsed.path.rstrip("/") != expected_path
or parsed.query
or parsed.fragment
):
raise UsdMObservationError(
f"Binance USD-M endpoint '{endpoint}' resolved to unapproved host or path '{url}'."
)
def read_account_observation(
exchange: Any,
*,
source_profile: str,
host: str,
now: Callable[[], datetime],
absolute_tolerance: float = DEFAULT_OBSERVATION_ABSOLUTE_TOLERANCE,
) -> dict[str, Any]:
"""Read and normalize one fail-closed, single-asset USD-M observation."""
if not math.isfinite(absolute_tolerance) or absolute_tolerance < 0:
raise UsdMObservationError("observation absolute tolerance must be non-negative and finite")
def close_enough(left: float, right: float) -> bool:
return math.isclose(View on GitHub (pinned to 80ffdda44c)
Solutions
- Remove custom url overrides from the ccxt client config so ccxt's stock fapi.binance.com URLs are used
- Ensure set_sandbox_mode is not rewriting fapi URLs before the assertion if you intend live usdm
- Pin a ccxt version compatible with the endpoint map assert_exchange_endpoints expects
- Print ex.urls['api'] (fapi entries) to identify exactly which URL violates the pin, then eliminate that override
Example fix
# before
client_config = {'urls': {'api': {'fapiPublic': 'https://fapi.binance.com/fapi/v1/?x=1'}}}
# after
client_config = {} # use ccxt defaults: https://fapi.binance.com, exact paths, no query Defensive patterns
Strategy: validation
Validate before calling
from urllib.parse import urlparse
for endpoint, url in resolved_fapi_urls(ex).items():
p = urlparse(url)
assert p.scheme == 'https' and p.hostname == 'fapi.binance.com'
assert p.port is None and not p.query and not p.fragment Type guard
def endpoint_is_pinned(url: str, expected_path: str) -> bool:
p = urlparse(url)
return (p.scheme == 'https' and p.hostname == 'fapi.binance.com'
and p.port is None and p.path.rstrip('/') == expected_path
and not p.query and not p.fragment) Try / catch
from trading.connectors.binance.usdm import UsdMObservationError
try:
assert_exchange_endpoints(ex)
except UsdMObservationError as exc:
logger.error('endpoint pin failed: %s — inspect ex.urls', exc)
raise Prevention
- Don't rewrite ccxt URLs; configure proxies via ccxt options
- Pin ccxt version
- Smoke-test endpoint resolution at deploy time
- Treat any endpoint-pin failure as a config bug, not transient
When it happens
Trigger: A ccxt client whose fapi endpoint URLs resolve with an http scheme, a different hostname (proxy, testnet domain, regional mirror), an explicit :443 port, a trailing path mismatch, or a ?query/#fragment appended. Triggered whenever _exchange builds a usdm client, i.e. on every public trading call (get_quote, place_order, etc.).
Common situations: Injecting custom URLs or proxies into ccxt config; enabling set_sandbox_mode before the assertion so ccxt swaps in testnet URLs; ccxt version change altering the fapi URL map shape so lookups return unexpected values; corporate proxies rewriting URLs.
Related errors
- {exc}
- unsafe media URL: {error}
- OpenAI Codex OAuth only supports https://chatgpt.com/backend
- Configured profile is paper, but the resolved host '{host}'
- Configured profile is live, but the resolved host '{host}' i
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/ed12e9a14e3a14e4.
Report an issue: GitHub.