ZhuLinsen/daily_stock_analysis · error · ValueError

unsupported technical alert_type: {alert_type}

Error message

unsupported technical alert_type: {alert_type}

What it means

Raised at the end of normalize_indicator_parameters (src/services/alert_indicators.py:88) when alert_type does not match any of the five supported technical indicators: ma_price_cross, rsi_threshold, macd_cross, kdj_cross, cci_threshold. It is an exhaustive-match error: any other string falls through all if-branches to this raise, with the offending alert_type interpolated into the message.

Source

Thrown at src/services/alert_indicators.py:88

            "signal_period": _int_in_range(parameters.get("signal_period"), "signal_period", default=9),
        }
        return _ensure_required_bars_fetchable(alert_type, normalized)
    if alert_type == "kdj_cross":
        normalized = {
            "direction": _direction(parameters.get("direction"), CROSS_DIRECTIONS, default="bullish_cross"),
            "period": _int_in_range(parameters.get("period"), "period", default=9),
            "k_period": _int_in_range(parameters.get("k_period"), "k_period", default=3),
            "d_period": _int_in_range(parameters.get("d_period"), "d_period", default=3),
        }
        return _ensure_required_bars_fetchable(alert_type, normalized)
    if alert_type == "cci_threshold":
        normalized = {
            "direction": _direction(parameters.get("direction"), ABOVE_BELOW_DIRECTIONS, default="above"),
            "period": _int_in_range(parameters.get("period"), "period", default=14),
            "threshold": _finite_float(parameters.get("threshold"), "threshold"),
        }
        return _ensure_required_bars_fetchable(alert_type, normalized)
    raise ValueError(f"unsupported technical alert_type: {alert_type}")


def compute_required_bars(alert_type: str, params: Dict[str, Any]) -> int:
    if alert_type == "ma_price_cross":
        return int(params["window"]) + 1
    if alert_type == "rsi_threshold":
        return int(params["period"]) + 1
    if alert_type == "macd_cross":
        return int(params["slow_period"]) + int(params["signal_period"]) + 1
    if alert_type == "kdj_cross":
        return int(params["period"]) + int(params["k_period"]) + int(params["d_period"]) + 1
    if alert_type == "cci_threshold":
        return int(params["period"]) + 1
    raise ValueError(f"unsupported technical alert_type: {alert_type}")


def compute_requested_days(alert_type: str, params: Dict[str, Any]) -> int:
    required_bars = compute_required_bars(alert_type, params)

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Use one of the five supported alert_type values exactly: ma_price_cross, rsi_threshold, macd_cross, kdj_cross, cci_threshold.
  2. Check for typos/whitespace/case in the submitted alert_type string.
  3. If you need a new indicator, implement its branch in both normalize_indicator_parameters and compute_required_bars, plus an evaluator, before accepting the type at the API.
  4. Validate alert_type against the supported set at the API schema layer to return 422 instead of a 500-flavored ValueError.

Example fix

// before
{ "alert_type": "macdcross", "parameters": { "fast_period": 12, "slow_period": 26 } }

// after
{ "alert_type": "macd_cross", "parameters": { "fast_period": 12, "slow_period": 26 } }
Defensive patterns

Strategy: type-guard

Validate before calling

SUPPORTED = {'ma_price_cross', 'rsi_threshold', 'macd_cross', 'kdj_cross', 'cci_threshold'}
alert_type = (alert_type or '').strip()
if alert_type not in SUPPORTED:
    raise ValueError(f'alert_type must be one of {sorted(SUPPORTED)}')

Type guard

SUPPORTED_ALERT_TYPES = frozenset({'ma_price_cross','rsi_threshold','macd_cross','kdj_cross','cci_threshold'})
def is_supported_alert_type(t: str) -> bool:
    return isinstance(t, str) and t in SUPPORTED_ALERT_TYPES

Try / catch

try:
    normalize_indicator_parameters(alert_type, params)
except ValueError as e:
    if 'unsupported technical alert_type' in str(e):
        return bad_request(f'unknown alert_type: {alert_type!r}')
    raise

Prevention

When it happens

Trigger: Creating/updating a technical alert with a typo ("macdcross", "rsi", "cci_threashold"), a non-technical type routed to the wrong normalizer (e.g. "price_above" reaching the indicator path), or a new indicator name added elsewhere but not implemented here.

Common situations: Frontend dropdown values out of sync with backend enum; copy-paste from docs with a renamed indicator; upstream code adding an alert_type without extending this dispatcher (and compute_required_bars which must stay in sync).

Related errors


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