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
- Compute thresholds defensively: use a fallback constant when the derived stat is NaN (check pd.notna / math.isfinite first).
- Reject or clamp non-finite values at the API boundary before persistence.
- 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
- Check pd.notna()/math.isfinite on any data-derived threshold before persisting it.
- Use large finite bounds (1e9) instead of float('inf') sentinels.
- Disallow NaN/Infinity at JSON parse settings (Python json.loads accepts them by default — reject explicitly).
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
- {field_name} must be an integer
- unsupported alert_type for current EventMonitor runtime: {al
- Event alert rules must be a JSON array
- Event alert rules list must contain only objects; invalid en
- Event alert rule must be an object
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/8b9f2b35040cf599.
Report an issue: GitHub.