ZhuLinsen/daily_stock_analysis · error · ValueError

invalid {field_name}: {value}

Error message

invalid {field_name}: {value}

What it means

Raised by _int_in_range (src/services/alert_indicators.py:380) when a numeric field (window, period, fast_period, slow_period, signal_period, k_period, d_period) cannot be converted with int() at all — the except (TypeError, ValueError) branch. This is the 'not a number' case, distinct from the 'number but not integer-formatted' and 'out of range' cases.

Source

Thrown at src/services/alert_indicators.py:380

            f"{alert_type} periods require {required_bars} bars, "
            f"but at most {MAX_REQUESTED_DAYS} days can be requested"
        )
    return params


def _direction(value: Any, allowed: frozenset[str], *, default: str) -> str:
    direction = str(value or default).strip().lower()
    if direction not in allowed:
        raise ValueError(f"invalid direction: {direction}")
    return direction


def _int_in_range(value: Any, field_name: str, *, default: int, minimum: int = 2, maximum: int = 250) -> int:
    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(

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Send plain integers (or numeric strings like "12") for period-like fields.
  2. Use a number input / parseInt on the frontend so non-numeric text cannot be submitted.
  3. Leave the field absent or empty to take the documented default rather than sending junk.

Example fix

// before
{ "alert_type": "rsi_threshold", "parameters": { "period": "14天", "threshold": 70 } }

// after
{ "alert_type": "rsi_threshold", "parameters": { "period": 14, "threshold": 70 } }
Defensive patterns

Strategy: type-guard

Validate before calling

INT_FIELDS = {'window','period','fast_period','slow_period','signal_period','k_period','d_period'}
for k, v in params.items():
    if k in INT_FIELDS:
        try:
            int(v)
        except (TypeError, ValueError):
            raise ValueError(f'{k} must be an integer, got {v!r}')

Type guard

def is_int_like(v) -> bool:
    if v is None or v == '':
        return True  # takes default
    try:
        int(v); return True
    except (TypeError, ValueError):
        return False

Try / catch

try:
    normalize_indicator_parameters(alert_type, params)
except ValueError as e:
    if str(e).startswith('invalid ') or 'must be' in str(e):
        return bad_request(str(e))
    raise

Prevention

When it happens

Trigger: parameters like {"period": "twelve"}, {"period": "12a"}, {"period": None-with-no-default?} — note None and "" take the default instead — or {"period": [12]} / {"period": {"v": 12}} where int() raises TypeError on list/dict.

Common situations: Free-text form inputs instead of number inputs; JSON payload passing nested objects for a scalar field; localized number strings ("12,5") or currency symbols surviving from a UI.

Related errors


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