HKUDS/Vibe-Trading · error · ValueError

FxRateTable entries must be FxRate, got {type(entry).__name_

Error message

FxRateTable entries must be FxRate, got {type(entry).__name__}

What it means

FxRateTable validates that every value in its rates mapping is an FxRate instance. Mixing in dicts, floats, or tuples fails immediately with the offending type name, because the table relies on FxRate's own invariants (normalized currency/date, positive rate).

Source

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

    """

    quote_currency: str
    rates: Mapping[tuple[str, date], FxRate] = field(default_factory=dict)

    def __post_init__(self) -> None:
        """Validate the quote currency and every entry's consistency.

        Raises:
            ValueError: If ``quote_currency`` is invalid, a value is not an
                ``FxRate``, an entry quotes against a different currency than
                the table's, or an entry is stored under a key that does not
                match its own ``(base_currency, date)``.
        """
        quote = normalize_currency(self.quote_currency, field_name="quote_currency")
        rates = dict(self.rates)
        for key, entry in rates.items():
            if not isinstance(entry, FxRate):
                raise ValueError(
                    f"FxRateTable entries must be FxRate, got {type(entry).__name__}"
                )
            if entry.quote_currency != quote:
                raise ValueError(
                    f"FxRate {entry.base_currency}/{entry.quote_currency}@"
                    f"{entry.date} does not quote against this table's "
                    f"currency {quote!r}; a table may only hold rates quoted "
                    "against one reporting currency"
                )
            expected_key = (entry.base_currency, entry.date)
            if key != expected_key:
                raise ValueError(
                    f"FxRate stored under key {key!r} does not match its own "
                    f"(base_currency, date) = {expected_key!r}"
                )
        object.__setattr__(self, "quote_currency", quote)
        object.__setattr__(self, "rates", MappingProxyType(rates))

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Construct FxRate objects first and use those as values: rates={('EUR', d): FxRate('EUR','USD',d,1.0850)}
  2. Or use the FxRateTable.from_rates(iterable_of_FxRate) factory, which builds the keyed mapping for you

Example fix

# before
FxRateTable(quote_currency='USD', rates={('EUR', d): 1.0850})
# after
FxRateTable(quote_currency='USD', rates={('EUR', d): FxRate('EUR','USD',d,1.0850)})
Defensive patterns

Strategy: type-guard

Validate before calling

assert all(isinstance(v, FxRate) for v in rates.values())

Type guard

from agent.src.entities.cashflow import FxRate
def all_fx_rates(mapping) -> bool:
    return all(isinstance(v, FxRate) for v in mapping.values())

Try / catch

try:
    FxRateTable(quote_currency=q, rates=mapping)
except ValueError as e:
    if 'must be FxRate' in str(e):
        mapping = {k: FxRate(k[0], q, k[1], v['rate']) for k, v in mapping.items()}

Prevention

When it happens

Trigger: FxRateTable(quote_currency='USD', rates={('EUR', d): {'rate': 1.08}}) or rates={('EUR', d): 1.08}.

Common situations: Building a table from raw parsed rows without an FxRate step; deserializing a mapping whose values lost their type; storing plain numbers for convenience in prototypes.

Related errors


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