{"record":{"id":"8fb34e831774d143","repo":"HKUDS/Vibe-Trading","slug":"window-must-be-1-got-window","errorCode":null,"errorMessage":"window must be >= 1, got {window}","messagePattern":"window must be >= 1, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/tools/pattern_tool.py","lineNumber":35,"sourceCode":"from src.tools.path_utils import safe_run_dir\n\n\n# ---------------------------------------------------------------------------\n# Pattern detection functions\n# ---------------------------------------------------------------------------\n\ndef find_peaks_valleys(close: pd.Series, window: int = 5) -> dict:\n    \"\"\"Detect peaks and valleys in a price series.\n\n    Args:\n        close: Closing price series.\n        window: Half-window size; effective window is 2*window+1.\n\n    Returns:\n        Dict with keys \"peaks\" and \"valleys\", each a list of integer indices.\n    \"\"\"\n    if window < 1:\n        raise ValueError(f\"window must be >= 1, got {window}\")\n    n = len(close)\n    if n < 2 * window + 1:\n        return {\"peaks\": [], \"valleys\": []}\n\n    values = close.values.astype(float)\n    peaks, valleys = [], []\n\n    for i in range(window, n - window):\n        seg = values[i - window : i + window + 1]\n        if np.isnan(values[i]):\n            continue\n        seg = seg[~np.isnan(seg)]\n        if len(seg) == 0:\n            continue\n        if values[i] == np.max(seg):\n            peaks.append(i)\n        if values[i] == np.min(seg):\n            valleys.append(i)","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/tools/pattern_tool.py#L17-L53","documentation":"find_peaks_valleys uses a centered window of size 2*window+1 for local-extrema detection; window < 1 makes the comparison meaningless (and would break slicing), so it raises immediately. Note: too-short series (n < 2*window+1) do NOT raise — they return empty peak/valley lists.","triggerScenarios":"Calling find_peaks_valleys (or pattern tools support_resistance/head_and_shoulders/double_top_bottom/triangle/broadening that forward a window) with window=0 or a negative value.","commonSituations":"Defaulting window to 0 in config, or computing window from a tunable that can be zero.","solutions":["Use window >= 1 (typical 3–5)","Clamp: window = max(1, int(user_value))","Validate pattern_tool params before dispatch"],"exampleFix":"# before\nfind_peaks_valleys(close, window=0)\n# after\nfind_peaks_valleys(close, window=max(1, window))","handlingStrategy":"validation","validationCode":"window = int(window)\nif window < 1:\n    raise ArgumentError(\"window must be >= 1\")\n# short series return empty results, not errors","typeGuard":"def valid_peak_window(w: object) -> bool:\n    return isinstance(w, int) and w >= 1","tryCatchPattern":"try:\n    pivots = find_peaks_valleys(close, window=window)\nexcept ValueError as e:\n    if \"window must be >= 1\" in str(e):\n        pivots = find_peaks_valleys(close, window=max(1, window))","preventionTips":["Clamp user tuning params to tool minimums","Keep separate window knobs for peaks vs slope (min 1 vs min 2)","Check series length vs 2*window+1 to anticipate empty results"],"tags":["pattern-tool","window-validation","input-validation"],"backgroundTag":"argument-range-validation-failed","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}