{"record":{"id":"f672bced5cb02b2a","repo":"HKUDS/Vibe-Trading","slug":"groups-array-cannot-be-empty","errorCode":null,"errorMessage":"groups array cannot be empty","messagePattern":"groups array cannot be empty","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/crossvalidation.py","lineNumber":311,"sourceCode":"        n_folds: Number of folds, at least :data:`MIN_FOLDS`.\n        embargo_fraction: Fraction of unique ordered groups embargoed after each test block.\n\n    Yields:\n        One :class:`Split` per fold, with ``train`` and ``test`` containing row indices.\n\n    Raises:\n        ValueError: If ``n_folds`` is invalid, fewer unique groups than folds exist,\n            or ``embargo_fraction`` is out of bounds.\n    \"\"\"\n    if n_folds < MIN_FOLDS:\n        raise ValueError(f\"n_folds must be at least {MIN_FOLDS}, got {n_folds}\")\n    if not 0.0 <= embargo_fraction < 1.0:\n        raise ValueError(f\"embargo_fraction must be in [0, 1), got {embargo_fraction}\")\n\n    grp_array = np.asarray(groups)\n    n_samples = len(grp_array)\n    if n_samples == 0:\n        raise ValueError(\"groups array cannot be empty\")\n\n    # Find unique groups preserving chronological order of appearance\n    unique_groups, first_indices = np.unique(grp_array, return_index=True)\n    # Sort by appearance order\n    order = np.argsort(first_indices)\n    unique_groups = unique_groups[order]\n    n_groups = len(unique_groups)\n\n    if n_groups < n_folds:\n        raise ValueError(f\"{n_groups} unique groups cannot make {n_folds} folds\")\n\n    # Map each group to its member row indices\n    group_to_rows: dict[object, np.ndarray] = {}\n    for idx, g in enumerate(grp_array):\n        group_to_rows.setdefault(g, []).append(idx)\n    for g in group_to_rows:\n        group_to_rows[g] = np.array(group_to_rows[g], dtype=int)\n","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/crossvalidation.py#L293-L329","documentation":"group_purged_kfold_splits needs a groups array assigning each observation to a group (e.g. ticker, day, session); an empty array gives no basis for splitting and is rejected before any fold construction.","triggerScenarios":"Calling group_purged_kfold_splits(X, groups=np.array([])) or with an empty list, e.g. because the grouping column was dropped or the frame was pre-filtered to zero rows.","commonSituations":"Empty dataframe after date filtering or NaN drops, groups column selected by a wrong name yielding an empty Series, or running a backtest loop over a period with no data.","solutions":["Check the sample is non-empty before splitting; fix upstream filtering that emptied it","Verify the groups column name exists and aligns with X's rows","Fall back to purged_kfold_splits with label_end_times when no grouping applies"],"exampleFix":"// before\nsplits = list(group_purged_kfold_splits(X_empty, groups=g_empty, n_folds=5))\n// after\nif len(X) == 0:\n    raise ValueError('no data for this period')\nsplits = list(group_purged_kfold_splits(X, groups=df['ticker'], n_folds=5))","handlingStrategy":"validation","validationCode":"groups = np.asarray(groups)\nassert groups.size > 0, 'groups array is empty'\nassert len(groups) == len(X)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check dataframe non-empty after filters","Validate group column exists and has no all-NaN"],"tags":["crossvalidation","group-kfold","empty-input","quantlib"],"backgroundTag":"empty-input-array","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}