Skip to content
7 changes: 5 additions & 2 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -6869,8 +6869,11 @@ def get_slice_bound(self, label, side: Literal["left", "right"]) -> int:
try:
return self._searchsorted_monotonic(label, side)
except ValueError:
# raise the original KeyError
raise err from None
raise KeyError(
f"Cannot get {side} slice bound for non-monotonic index "
f"with a missing label {original_label!r}. "
"Either sort the index or specify an existing label."
) from None

if isinstance(slc, np.ndarray):
# get_loc may return a boolean array, which
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -564,9 +564,10 @@ def test_getitem_setitem_integer_slice_keyerrors(self):

# non-monotonic, raise KeyError
df2 = df.iloc[list(range(5)) + list(range(5, 10))[::-1]]
with pytest.raises(KeyError, match=r"^3$"):
msg = "non-monotonic index with a missing label 3"
with pytest.raises(KeyError, match=msg):
df2.loc[3:11]
with pytest.raises(KeyError, match=r"^3$"):
with pytest.raises(KeyError, match=msg):
df2.loc[3:11] = 0

def test_fancy_getitem_slice_mixed(self, float_frame, float_string_frame):
Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/indexes/numeric/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,10 +600,11 @@ def test_slice_locs_na(self):

def test_slice_locs_na_raises(self):
index = Index([np.nan, 1, 2])
with pytest.raises(KeyError, match="1.5"):
msg = "non-monotonic index with a missing label 1.5"
with pytest.raises(KeyError, match=msg):
index.slice_locs(start=1.5)

with pytest.raises(KeyError, match="1.5"):
with pytest.raises(KeyError, match=msg):
index.slice_locs(end=1.5)


Expand Down
5 changes: 3 additions & 2 deletions pandas/tests/indexing/test_loc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3162,9 +3162,10 @@ def test_loc_getitem_setitem_integer_slice_keyerrors(self):

# non-monotonic, raise KeyError
s2 = ser.iloc[list(range(5)) + list(range(9, 4, -1))]
with pytest.raises(KeyError, match=r"^3$"):
msg = "non-monotonic index with a missing label 3"
with pytest.raises(KeyError, match=msg):
s2.loc[3:11]
with pytest.raises(KeyError, match=r"^3$"):
with pytest.raises(KeyError, match=msg):
s2.loc[3:11] = 0

def test_loc_getitem_iterator(self, string_series):
Expand Down
7 changes: 7 additions & 0 deletions pandas/tests/series/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,13 @@ def test_setitem_empty_indexer(indexer, val):
tm.assert_frame_equal(df, expected)


def test_loc_non_monotonic_index_with_a_missing_label():
msg = "Cannot get left slice bound for non-monotonic index with a missing label 4"
ser = Series([3, 6, 7, 6], index=[3, 8, 7, 6])
with pytest.raises(KeyError, match=msg):
ser.loc[4:7]


class TestDeprecatedIndexers:
@pytest.mark.parametrize("key", [{1}, {1: 1}])
def test_getitem_dict_and_set_deprecated(self, key):
Expand Down
Loading