{"record":{"id":"fe0150c160938758","repo":"ZhuLinsen/daily_stock_analysis","slug":"field-name-must-be-between-minimum-and-maximu","errorCode":null,"errorMessage":"{field_name} must be between {minimum} and {maximum}","messagePattern":"(.+?) must be between (.+?) and (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":400,"severity":"error","filePath":"src/services/alert_indicators.py","lineNumber":384,"sourceCode":"\n\ndef _direction(value: Any, allowed: frozenset[str], *, default: str) -> str:\n    direction = str(value or default).strip().lower()\n    if direction not in allowed:\n        raise ValueError(f\"invalid direction: {direction}\")\n    return direction\n\n\ndef _int_in_range(value: Any, field_name: str, *, default: int, minimum: int = 2, maximum: int = 250) -> int:\n    raw_value = default if value is None or value == \"\" else value\n    try:\n        number = int(raw_value)\n    except (TypeError, ValueError) as exc:\n        raise ValueError(f\"invalid {field_name}: {value}\") from exc\n    if str(raw_value).strip() not in {str(number), f\"{number}.0\"}:\n        raise ValueError(f\"{field_name} must be an integer\")\n    if number < minimum or number > maximum:\n        raise ValueError(f\"{field_name} must be between {minimum} and {maximum}\")\n    return number\n\n\ndef _finite_float(value: Any, field_name: str) -> float:\n    try:\n        number = float(value)\n    except (TypeError, ValueError) as exc:\n        raise ValueError(f\"invalid {field_name}: {value}\") from exc\n    if not isfinite(number):\n        raise ValueError(f\"{field_name} must be finite\")\n    return number\n\n\ndef _float_in_range(\n    value: Any,\n    field_name: str,\n    *,\n    minimum: float,","sourceCodeStart":366,"sourceCodeEnd":402,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/services/alert_indicators.py#L366-L402","documentation":"Raised by _int_in_range (src/services/alert_indicators.py:384) when an integer field parses fine but falls outside the inclusive range [minimum, maximum], which defaults to [2, 250] and applies to window, period, fast/slow/signal/k/d periods. Period-1 indicators need at least 2 points; 250 caps single-field history demand (see also error 327 for the summed-bars cap of 365).","triggerScenarios":"parameters like {\"window\": 1} or {\"window\": 0} (below minimum 2); {\"period\": 300} or {\"period\": 365} (above maximum 250). Note each individual field maxes at 250 even though the summed-bars check separately allows sums up to 365.","commonSituations":"Copy-pasting settings from another platform allowing period=1 (some RSI(1) tricks) or 300-day windows; template configs tuned for intraday bars reused on daily bars; 'more is smoother' period inflation.","solutions":["Clamp each integer field to 2..250 (e.g. window=200 is fine, window=300 is not).","If you need >250-day windows, that single field cannot express it; reconsider the indicator or raise the cap in code after verifying data availability.","Validate client-side with min=2 max=250 inputs."],"exampleFix":"// before\n{ \"alert_type\": \"ma_price_cross\", \"parameters\": { \"window\": 300 } }\n\n// after\n{ \"alert_type\": \"ma_price_cross\", \"parameters\": { \"window\": 250 } }","handlingStrategy":"validation","validationCode":"for k, v in params.items():\n    if k in INT_FIELDS:\n        n = int(v)\n        if not (2 <= n <= 250):\n            raise ValueError(f'{k} must be within 2..250; adjust the strategy instead of inflating periods')","typeGuard":"def is_int_in_2_250(v) -> bool:\n    try:\n        return 2 <= int(v) <= 250\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"try:\n    normalize_indicator_parameters(alert_type, params)\nexcept ValueError as e:\n    if 'must be between 2 and 250' in str(e):\n        params.update({k: min(250, max(2, int(v))) for k, v in params.items() if k in INT_FIELDS})\n        normalize_indicator_parameters(alert_type, params)\n    else:\n        raise","preventionTips":["Set min=2, max=250 on every period input in the UI.","Do not port period=1 tricks or 300-day windows from other platforms; redesign the alert instead.","Prefer defaults (9/12/14/20/26) unless backtests justify long windows."],"tags":["validation","range","alerts","parameters"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}