HKUDS/Vibe-Trading · error · UsdMObservationError
Binance USD-M field {name} must be finite
Error message
Binance USD-M field {name} must be finite What it means
Raised by _number when a field converts to float successfully but the result is not finite (NaN or +/-Inf). JSON parsers accept tokens like 'NaN'/'Infinity' or Python float('nan'), so this guard catches them before they poison downstream arithmetic. The {name} placeholder identifies which field (price, balance, positionAmt, etc.) is non-finite.
Source
Thrown at agent/src/trading/connectors/binance/usdm.py:327
def _canonical_symbol(symbol: str) -> str:
if not symbol.endswith("USDT") or len(symbol) <= 4 or not symbol.isalnum():
raise UsdMObservationError("Binance USD-M supports canonical */USDT symbols only")
return f"{symbol[:-4]}-USDT-PERP"
def _number(
value: Any,
name: str,
*,
non_negative: bool = False,
positive: bool = False,
) -> float:
try:
number = float(value)
except (TypeError, ValueError) as exc:
raise UsdMObservationError(f"Binance USD-M field {name} must be numeric") from exc
if not math.isfinite(number):
raise UsdMObservationError(f"Binance USD-M field {name} must be finite")
if positive and number <= 0:
raise UsdMObservationError(f"Binance USD-M field {name} must be positive")
if non_negative and number < 0:
raise UsdMObservationError(f"Binance USD-M field {name} must be non-negative")
return number
def _integer(value: Any, name: str) -> int:
number = _number(value, name, non_negative=True)
if not number.is_integer():
raise UsdMObservationError(f"Binance USD-M field {name} must be an integer")
return int(number)
def _configuration_hash(source_profile: str, host: str, absolute_tolerance: float) -> str:
payload = {
"schema_version": SCHEMA_VERSION,
"source_profile": source_profile,View on GitHub (pinned to 80ffdda44c)
Solutions
- Trace where the NaN/Infinity originated — usually an upstream division by zero or unset field
- Sanitize inputs: convert non-finite values to a rejected/zero default before passing payloads to the connector
- Fix fixtures that use float('nan') or 'Infinity' strings
- If the exchange genuinely sent NaN, retry the snapshot and report to Binance if persistent
Example fix
// before
row = {"symbol": "BTCUSDT", "positionAmt": "NaN"}
// after
row = {"symbol": "BTCUSDT", "positionAmt": "0"} Defensive patterns
Strategy: validation
Validate before calling
import math
def all_finite(row: dict, keys: list[str]) -> bool:
return all(
math.isfinite(float(row[k])) for k in keys if row.get(k) is not None
)
if not all_finite(row, ["positionAmt", "entryPrice"]):
row = sanitize(row) # drop/zero non-finite values Type guard
import math
def is_finite_number(value: Any) -> TypeGuard[float]:
try:
return math.isfinite(float(value))
except (TypeError, ValueError):
return False Try / catch
try:
obs = connector.read_account_observation(...)
except UsdMObservationError as exc:
if "must be finite" in str(exc):
row = coerce_non_finite_to_zero(row)
obs = connector.read_account_observation(...) # retry with sanitized data
else:
raise Prevention
- Filter NaN/Inf at ingestion boundaries (math.isfinite checks)
- Avoid float('nan') sentinel values in pipelines; use None
- Test fixtures must not contain 'NaN'/'Infinity' strings
When it happens
Trigger: A payload field is the string 'NaN' or 'Infinity' (Python's float() accepts these), or a computed/upstream value already containing NaN is fed back into the connector.
Common situations: Upstream components dividing by zero to produce NaN/inf and passing it along; exchange sending literal NaN in rare degenerate snapshots; fixtures using float('nan'); string interpolation of 'Infinity' from log-adjacent code.
Related errors
- {model}: {name} must be a finite number, got {numeric!r}
- {model}: {name} must be a finite number, got {numeric!r}
- {name} must be a finite number, got {value!r}
- Binance USD-M assets must include USDT
- Binance USD-M account totals are incoherent
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/fb3464d21b5d3eb2.
Report an issue: GitHub.