ZhuLinsen/daily_stock_analysis · error · ValueError

{field_name} must be finite

Error message

{field_name} must be finite

What it means

Raised by _finite_float (src/services/alert_indicators.py:394) when a float field converts successfully but is not finite — i.e. float('inf'), float('-inf'), or float('nan'). math.isfinite guards indicator thresholds against values that would make every comparison ('above'/'below') meaningless or always-false.

Source

Thrown at src/services/alert_indicators.py:394

    raw_value = default if value is None or value == "" else value
    try:
        number = int(raw_value)
    except (TypeError, ValueError) as exc:
        raise ValueError(f"invalid {field_name}: {value}") from exc
    if str(raw_value).strip() not in {str(number), f"{number}.0"}:
        raise ValueError(f"{field_name} must be an integer")
    if number < minimum or number > maximum:
        raise ValueError(f"{field_name} must be between {minimum} and {maximum}")
    return number


def _finite_float(value: Any, field_name: str) -> float:
    try:
        number = float(value)
    except (TypeError, ValueError) as exc:
        raise ValueError(f"invalid {field_name}: {value}") from exc
    if not isfinite(number):
        raise ValueError(f"{field_name} must be finite")
    return number


def _float_in_range(
    value: Any,
    field_name: str,
    *,
    minimum: float,
    maximum: float,
) -> float:
    number = _finite_float(value, field_name)
    if number < minimum or number > maximum:
        raise ValueError(f"{field_name} must be between {minimum:g} and {maximum:g}")
    return number


def _calculate_rsi(close: pd.Series, period: int) -> pd.Series:
    delta = close.diff()

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Compute thresholds defensively: use a fallback constant when the derived stat is NaN (check pd.notna / math.isfinite first).
  2. Reject or clamp non-finite values at the API boundary before persistence.
  3. Never let float('inf') through as an 'unbounded' sentinel — pick a large finite bound instead.

Example fix

# before
threshold = df['close'].max()  # NaN when df is empty
params = {'period': 14, 'threshold': threshold}

# after
raw = df['close'].max()
threshold = raw if pd.notna(raw) and math.isfinite(raw) else 100.0
params = {'period': 14, 'threshold': threshold}
Defensive patterns

Strategy: validation

Validate before calling

import math
t = params.get('threshold')
try:
    t = float(t)
except (TypeError, ValueError):
    raise ValueError('threshold must be numeric')
if not math.isfinite(t):
    raise ValueError('threshold must be finite (NaN/inf not allowed)')
params['threshold'] = t

Type guard

import math
def is_finite_number(v) -> bool:
    try:
        return math.isfinite(float(v))
    except (TypeError, ValueError):
        return False

Try / catch

try:
    normalize_indicator_parameters(alert_type, params)
except ValueError as e:
    if 'must be finite' in str(e):
        return bad_request('threshold must be a finite number')
    raise

Prevention

When it happens

Trigger: threshold values of Infinity/-Infinity/NaN in JSON-ish payloads (Python float('nan'), or strings "inf"/"nan"/"NaN" that float() accepts); NaN slipping in from a pandas computation (e.g. threshold derived from a rolling stat on sparse data) and forwarded without checking.

Common situations: Computing thresholds from data (max/min of an empty or all-NaN series yields NaN); JSON serializers that emit Infinity for unbounded values; user typing 'inf' in a numeric field.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/8b9f2b35040cf599. Report an issue: GitHub.