{"record":{"id":"b2916494e2edd295","repo":"HKUDS/Vibe-Trading","slug":"label-end-times-has-span-ends-size-entries-but-t","errorCode":null,"errorMessage":"label_end_times has {span_ends.size} entries but the sample has {n_samples}","messagePattern":"label_end_times has (.+?) entries but the sample has (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/quantlib/crossvalidation.py","lineNumber":157,"sourceCode":"        positions = np.searchsorted(starts, ends, side=\"right\") - 1\n        positions = np.clip(positions, np.arange(len(starts)), len(starts) - 1)\n        span_ends = positions.astype(int)\n    else:\n        span_ends = np.asarray(label_end_times, dtype=float)\n        if span_ends.ndim != 1:\n            raise ValueError(f\"label_end_times must be 1-D, got shape {span_ends.shape}\")\n        if span_ends.size == 0:\n            raise ValueError(\"label_end_times is empty\")\n        if not np.isfinite(span_ends).all():\n            raise ValueError(\"label_end_times holds a non-finite value\")\n        span_ends = span_ends.astype(int)\n        if (span_ends < np.arange(span_ends.size)).any():\n            raise ValueError(\n                \"a label cannot end before the observation it belongs to starts\"\n            )\n\n    if n_samples is not None and span_ends.size != n_samples:\n        raise ValueError(\n            f\"label_end_times has {span_ends.size} entries but the sample has {n_samples}\"\n        )\n    return span_ends\n\n\ndef _apply_purge_and_embargo(\n    label_ends: np.ndarray,\n    test_mask: np.ndarray,\n    embargo_size: int,\n) -> tuple[np.ndarray, int, int]:\n    \"\"\"Build a training mask that is purged of overlap and embargoed after.\n\n    Args:\n        label_ends: Last positional index each observation's label covers.\n        test_mask: Boolean mask of the test observations.\n        embargo_size: Observations embargoed immediately after each test block.\n\n    Returns:","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/quantlib/crossvalidation.py#L139-L175","documentation":"Raised by _as_label_spans when the label_end_times array has a different length than the sample it is meant to describe. The purging logic indexes label spans row-by-row, so a length mismatch would silently purge the wrong observations or crash later. The library fails fast with an explicit size comparison.","triggerScenarios":"Calling purged_kfold_splits/purged_walk_forward_splits/combinatorial_purged_splits/detect_boundary_leakage with label_end_times of length m while X (or n_samples) has n != m rows, e.g. labels computed on the full dataset but features filtered to a subset.","commonSituations":"Dropping NaN rows from features after computing labels, train/test pre-filtering, concatenating frames out of order, or passing labels from a different ticker/period than the sample.","solutions":["Align lengths: recompute or reindex label_end_times on exactly the rows of the sample (e.g. df.loc[X.index]","Check for accidental slicing of X (train-only frames) while passing full-length labels","Add an assert len(label_end_times) == len(X) before calling the splitter"],"exampleFix":"// before\nsplits = list(purged_kfold_splits(X.dropna(), n_folds=5, label_end_times=labels_full))\n// after\nX2 = X.dropna()\nlabels = labels_full[X2.index]\nsplits = list(purged_kfold_splits(X2, n_folds=5, label_end_times=labels))","handlingStrategy":"validation","validationCode":"assert len(label_end_times) == len(X), f'{len(label_end_times)} labels vs {len(X)} rows'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep labels attached to the frame (a column) instead of a separate array","After dropna/filter operations, subset labels with X.index"],"tags":["crossvalidation","shape-mismatch","data-validation","quantlib"],"backgroundTag":"array-length-mismatch","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}