HKUDS/Vibe-Trading · error · ValueError

rate must be numeric, got {self.rate!r}

Error message

rate must be numeric, got {self.rate!r}

What it means

FxRate.__post_init__ coerces rate to float and rejects non-numeric input (TypeError/ValueError from float()). FX rates must be numbers for translation arithmetic to be valid.

Source

Thrown at agent/src/entities/cashflow.py:492

        Raises:
            ValueError: If either currency code is invalid, the date is
                unsupported, or the rate is not finite and strictly positive.
        """
        object.__setattr__(
            self,
            "base_currency",
            normalize_currency(self.base_currency, field_name="base_currency"),
        )
        object.__setattr__(
            self,
            "quote_currency",
            normalize_currency(self.quote_currency, field_name="quote_currency"),
        )
        object.__setattr__(self, "date", normalize_date(self.date))
        try:
            rate = float(self.rate)
        except (TypeError, ValueError) as exc:
            raise ValueError(f"rate must be numeric, got {self.rate!r}") from exc
        if not math.isfinite(rate) or rate <= 0:
            raise ValueError(
                f"rate must be finite and strictly positive -- it is "
                f"quote-per-base units -- got {rate!r}; a zero or negative "
                "rate would silently zero out or flip the sign of every flow "
                "translated with it"
            )
        object.__setattr__(self, "rate", rate)


@dataclass(frozen=True)
class FxRateTable:
    """A lookup of FX rates, every entry quoted against one fixed currency.

    All entries must share the same ``quote_currency``: a table that mixed
    quote currencies would make "translate to X" ambiguous, so that is
    rejected at construction rather than left to whichever rate happens to be
    looked up first.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Parse/validate the rate column to float before constructing FxRate
  2. Treat missing rates as absent data: skip the entry (and rely on allow_stale or fail explicitly) rather than passing a sentinel string

Example fix

# before
FxRate('EUR','USD',d, rate='1.0850 USD')
# after
FxRate('EUR','USD',d, rate=1.0850)
Defensive patterns

Strategy: validation

Validate before calling

rate = float(str(raw_rate).replace(',', '').strip())
if math.isnan(rate): raise SkipRate(raw_rate)

Type guard

def is_numeric_rate(v) -> bool:
    return isinstance(v, (int, float)) and not isinstance(v, bool)

Try / catch

try:
    FxRate('EUR','USD',d, rate=raw)
except ValueError as e:
    if 'rate must be numeric' in str(e):
        skip_or_repair(raw)

Prevention

When it happens

Trigger: FxRate(base_currency='EUR', quote_currency='USD', date=d, rate='n/a') or rate=None or an unparseable string.

Common situations: FX rate columns from CSV with 'N/A', dashes, or thousands separators; API responses where the rate field is occasionally a string; optional lookups returning None.

Related errors


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