HKUDS/Vibe-Trading · error · ValuationError

{model}: {name} must be a number, got {value!r}

Error message

{model}: {name} must be a number, got {value!r}

What it means

require_positive first coerces the value with float(); if that raises TypeError/ValueError (non-numeric input like a string or None), it raises this 'must be a number' ValuationError. Used for values meaningless at/below zero (growth rates, share counts, etc.) in __post_init__, equity_bridge, sensitivity_grid, project_three_statement.

Source

Thrown at agent/src/quantlib/valuation/contracts.py:155

def require_positive(value: float, name: str, model: str) -> float:
    """Check a value that is meaningless at or below zero.

    Args:
        value: The value to check, e.g. a share count or a discount rate.
        name: Field name for the error message.
        model: Model name for the error message.

    Returns:
        ``value`` as a float.

    Raises:
        ValuationError: If the value is not a finite number greater than zero.
    """
    try:
        numeric = float(value)
    except (TypeError, ValueError) as exc:
        raise ValuationError(f"{model}: {name} must be a number, got {value!r}") from exc
    if not numeric > 0.0 or numeric != numeric or numeric in (float("inf"), float("-inf")):
        raise ValuationError(
            f"{model}: {name} must be a finite positive number, got {numeric}"
        )
    return numeric

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Convert to float explicitly at your boundary and fail with your own clearer message.
  2. Strip '%' and other decorations before parsing if your config uses formatted numbers.
  3. Use typed config (pydantic/dataclass with float fields) so strings never reach the library.

Example fix

# before
shares = row['shares']  # '1.2B'

# after
shares = parse_shares(row['shares'])  # returns 1_200_000_000.0, raises on 'n/a'
Defensive patterns

Strategy: type-guard

Validate before calling

try:
    value = float(value)
except (TypeError, ValueError):
    raise ValueError(f'expected a number, got {value!r}')

Type guard

def is_numeric(v):
    return isinstance(v, (int, float)) and not isinstance(v, bool)

Try / catch

except ValuationError as e:
    if 'must be a number' in str(e):
        value = parse_formatted(row[name])  # your parser

Prevention

When it happens

Trigger: Passing '5%', None, a dict, or an unparseable string where a positive float is required, e.g. a shares figure of 'n/a'.

Common situations: Config values left as strings ('0.05' parses, '5%' does not); Excel/CSV cells with text like 'n/a'; None defaults leaking into required parameters.

Related errors


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