{"record":{"id":"cc687e30fac4ad14","repo":"pandas-dev/pandas","slug":"start-end-ordering-requirement-is-violated-at-inde","errorCode":null,"errorMessage":"Start/End ordering requirement is violated at index {i}","messagePattern":"Start/End ordering requirement is violated at index (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/_numba/kernels/min_max_.py","lineNumber":96,"sourceCode":"            i_next = i\n\n    # NaN tracking to guarantee min_periods\n    valid_start = -min_periods\n\n    last_end = 0\n    last_start = -1\n\n    for i in range(N):\n        this_start = start[i].item()\n        this_end = end[i].item()\n\n        if dominators and dominators[-1] == i:\n            dominators.pop()\n\n        if not (\n            this_end > last_end or (this_end == last_end and this_start >= last_start)\n        ):\n            raise ValueError(\n                \"Start/End ordering requirement is violated at index \" + str(i)\n            )\n\n        stash_start = (\n            this_start if not dominators else min(this_start, start[dominators[-1]])\n        )\n        while candidates and candidates[0] < stash_start:\n            candidates.pop(0)\n\n        for k in range(last_end, this_end):\n            if not np.isnan(values[k]):\n                valid_start += 1\n                while valid_start >= 0 and np.isnan(values[valid_start]):\n                    valid_start += 1\n                while candidates and cmp(values[k], values[candidates[-1]], is_max):\n                    candidates.pop()  # Q.pop_back()\n                candidates.append(k)  # Q.push_back(k)\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/_numba/kernels/min_max_.py#L78-L114","documentation":"This error is raised inside the Numba-accelerated kernel for rolling minimum/maximum calculations (engine=\"numba\"). The kernel processes windowed extrema using a monotonicity assumption: each successive window's end-boundary must strictly advance, or if the end stays the same, the start must not decrease. This invariant lets the deque-based algorithm run in O(N) rather than re-scanning. When the start/end boundary arrays passed to the kernel violate this ordering, the algorithm cannot produce correct results and aborts.","triggerScenarios":"Calling Series.rolling(...).min(engine=\"numba\") or .max(engine=\"numba\") with variable-length or forward-looking window definitions whose boundary arrays are not monotonically ordered by end (and non-decreasing by start when ends tie). This arises with custom window generators, forward windows, or manually constructed start/end index arrays that interleave or reverse.","commonSituations":"Using Rolling/Expanding with a step parameter or custom window array alongside engine=\"numba\" in a pandas version where the numba path has stricter ordering constraints than the default Cython path. Migrating from the default engine to engine=\"numba\" and discovering the window semantics differ. Constructing windows from irregular time-series boundaries (e.g., session-based or event-based windows) where end boundaries can revisit or stay flat while starts move backwards.","solutions":["Switch to the default engine (remove engine=\"numba\" or set engine=\"cython\") which has looser ordering requirements.","Ensure your window boundaries are sorted so that end[i] is strictly increasing, or non-decreasing with non-decreasing start when ends are equal, before passing them to the rolling operation.","If using variable windows, pre-sort or reindex your data so windows advance monotonically, then re-map results back to the original order.","Verify your pandas version — newer versions may relax or tighten these constraints; check the release notes for rolling numba changes."],"exampleFix":"# before\ns.rolling(window=custom_bounds, engine=\"numba\").min()\n\n# after — use default engine which accepts arbitrary window orderings\ns.rolling(window=custom_bounds).min()","handlingStrategy":"validation","validationCode":"# Before calling rolling min/max with numba, verify window ordering\nstart = np.asarray(start_bounds)\nend = np.asarray(end_bounds)\nfor i in range(1, len(end)):\n    if not (end[i] > end[i-1] or (end[i] == end[i-1] and start[i] >= start[i-1])):\n        raise ValueError(f\"Window ordering violated at index {i}; use default engine\")","typeGuard":null,"tryCatchPattern":"try:\n    result = s.rolling(window=bounds, engine=\"numba\").min()\nexcept ValueError as e:\n    if \"Start/End ordering\" in str(e):\n        # fall back to default engine\n        result = s.rolling(window=bounds).min()\n    else:\n        raise","preventionTips":["Prefer the default Cython engine for rolling operations unless you specifically need Numba performance.","Sort or reindex your data so window boundaries advance monotonically before using engine='numba'.","Check the pandas release notes when upgrading — numba rolling constraints may change between versions."],"tags":["pandas","numba","rolling","windowing","valueerror"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}