{"record":{"id":"4c59940c4ed35bb2","repo":"pandas-dev/pandas","slug":"cannot-do-a-non-empty-take","errorCode":null,"errorMessage":"cannot do a non-empty take","messagePattern":"cannot do a non-empty take","errorType":"exception","errorClass":"IndexError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/arrow/array.py","lineNumber":2091,"sourceCode":"            When `indices` contains negative values other than ``-1``\n            and `allow_fill` is True.\n\n        See Also\n        --------\n        numpy.take\n        api.extensions.take\n\n        Notes\n        -----\n        ExtensionArray.take is called by ``Series.__getitem__``, ``.loc``,\n        ``iloc``, when `indices` is a sequence of values. Additionally,\n        it's called by :meth:`Series.reindex`, or any other method\n        that causes realignment, with a `fill_value`.\n        \"\"\"\n        indices_array = np.asanyarray(indices)\n\n        if len(self._pa_array) == 0 and (indices_array >= 0).any():\n            raise IndexError(\"cannot do a non-empty take\")\n        if indices_array.size > 0 and indices_array.max() >= len(self._pa_array):\n            raise IndexError(\"out of bounds value in 'indices'.\")\n\n        if allow_fill:\n            fill_mask = indices_array < 0\n            if fill_mask.any():\n                validate_indices(indices_array, len(self._pa_array))\n                # TODO(ARROW-9433): Treat negative indices as NULL\n                indices_array = pa.array(indices_array, mask=fill_mask)\n                result = self._pa_array.take(indices_array)\n                if isna(fill_value):\n                    return self._from_pyarrow_array(result)\n                # TODO: ArrowNotImplementedError: Function fill_null has no\n                # kernel matching input types (array[string], scalar[string])\n                result = self._from_pyarrow_array(result)\n                result[fill_mask] = fill_value\n                return result\n                # return type(self)(pc.fill_null(result, pa.scalar(fill_value)))","sourceCodeStart":2073,"sourceCodeEnd":2109,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/arrow/array.py#L2073-L2109","documentation":"ExtensionArray.take with allow_fill semantics refuses to produce a non-empty result from an empty source array: if self._pa_array has length 0 but any requested index is >= 0 (a real position, not a fill marker), there is nothing to copy from. This is distinct from out-of-bounds: it specifically catches the empty-input degenerate case before the bounds check.","triggerScenarios":"Calling .take(indices) or .reindex(...) with allow_fill on a zero-length ArrowExtensionArray where indices contains at least one non-negative entry, e.g. empty_arr.take([0, -1]).","commonSituations":"Reindexing an empty DataFrame/Series against a non-empty target; take() on dynamically-filtered arrays that ended up empty; fill_value-based reindex on empty frames.","solutions":["Guard upstream: check len(arr) > 0 before calling take/reindex, or filter the requested indices to only fill positions.","Construct the target array so it is non-empty before the operation.","Use Series.reindex with a fill_value on a non-empty source instead of taking from an empty one."],"exampleFix":"// before\narr = pd.array([], dtype=\"int64[pyarrow]\")\narr.take([0, 1], allow_fill=True)\n// after\narr = pd.array([], dtype=\"int64[pyarrow]\")\nif len(arr) > 0:\n    arr.take([0, 1], allow_fill=True)","handlingStrategy":"validation","validationCode":"def safe_take(arr, indices, allow_fill=False, fill_value=None):\n    if len(arr) == 0:\n        if allow_fill and fill_value is not None:\n            n = len(indices)\n            return type(arr)([fill_value] * n, dtype=arr.dtype)\n        return arr.take(indices, allow_fill=False)\n    return arr.take(indices, allow_fill=allow_fill, fill_value=fill_value)","typeGuard":"def take_is_safe(arr, indices) -> bool:\n    import numpy as np\n    if len(arr) == 0:\n        return not (np.asanyarray(indices) >= 0).any()\n    return True","tryCatchPattern":"try:\n    arr.take(indices, allow_fill=True)\nexcept IndexError as e:\n    if \"non-empty take\" in str(e):\n        # produce a filled result manually\n        ...\n    raise","preventionTips":["Check len(arr) > 0 before reindex/take with allow_fill.","Filter indices to fill-only (-1) when the source is empty."],"tags":["pyarrow","take","empty-array","indexerror"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}