HKUDS/Vibe-Trading · error · UsdMObservationError
Binance USD-M field {name} must be non-negative
Error message
Binance USD-M field {name} must be non-negative What it means
Raised by _number when a field is numeric, finite, but negative while non_negative=True was requested (or via _integer which sets non_negative=True). Used for counts and amounts that can be zero but never negative, e.g. update indices, seat numbers, quantities. The {name} placeholder identifies the field.
Source
Thrown at agent/src/trading/connectors/binance/usdm.py:331
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,
"market_type": "usdm",
"host": host,
"account_endpoint": "/fapi/v2/account",
"position_endpoint": "/fapi/v3/positionRisk",View on GitHub (pinned to 80ffdda44c)
Solutions
- Inspect the named field in the raw payload; decide whether -1/negative is a sentinel meaning 'missing' and map it to None/0 before parsing
- Fix sign handling in upstream computations
- Update fixtures to non-negative values
- If the exchange legitimately returns -1 sentinels, translate them before calling the connector
Example fix
// before
_number(payload.get("updateTime"), "updateTime", non_negative=True) # -1
// after
raw = payload.get("updateTime")
_number(0 if raw == -1 else raw, "updateTime", non_negative=True) Defensive patterns
Strategy: validation
Validate before calling
def non_negative(v) -> float:
n = float(v)
if n < 0:
raise ValueError(f"negative value: {v}")
return n
payload["updateTime"] = max(0, payload.get("updateTime", 0)) Try / catch
try:
obs = connector.read_account_observation(...)
except UsdMObservationError as exc:
if "must be non-negative" in str(exc):
payload = translate_sentinels(payload) # -1 -> 0/None
obs = connector.read_account_observation(...)
else:
raise Prevention
- Translate exchange -1 sentinels at the ingestion layer
- Use integer-safe arithmetic for counts and timestamps
- Clamp computed values to >= 0 when negatives are meaningless
When it happens
Trigger: A field like updateTime, an index, or an amount is negative in the payload; e.g. positionAmt-style amounts extracted with non_negative=True, or a timestamp/count that underflowed.
Common situations: Sign flipped during upstream arithmetic; mock data with negative counts; API change returning -1 sentinels for 'not available'; timezone/epoch arithmetic producing negative timestamps.
Related errors
- Binance USD-M field {name} must be positive
- Binance USD-M assets must include USDT
- Binance USD-M account totals are incoherent
- Binance USD-M {name} payload is invalid
- Binance USD-M Shadow Account requires one-way position mode
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/509ea4daaf6ee17a.
Report an issue: GitHub.