Skip to content
Open
Changes from 1 commit
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
BUG: Improve Index level validation to reject all NA-like values and …
…enhance error handling for boolean levels
  • Loading branch information
whyvineet committed Aug 25, 2025
commit d88124760a5b96441b0a7f73d73cb225aca1143f
36 changes: 17 additions & 19 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2085,20 +2085,24 @@ def _validate_index_level(self, level) -> None:

"""
# Explicitly raise for missing/null values to match pandas convention
# Also reject all NA-like values (np.nan, pd.NA, pd.NaT, etc.)
if isna(level):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what if index.name is a na-like scalar?

raise KeyError(
"Requested level is NA/NaN/NaT, which is not a valid level name"
)

# Standard integer check, but reject bool
if lib.is_integer(level) and not isinstance(level, bool):
# If the index itself is named as integer, accept
if lib.is_integer(self.name) and level == self.name:
return
# Only allow 0 and -1 for a single-level Index
if level in (0, -1):
return
if level < 0:
# Reject booleans unless the index name is actually a boolean and matches
if isinstance(level, bool):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isnt this handled in the existing elif level != self.name check?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense... I'll keep the same.

if level != self.name:
raise KeyError(
f"Requested level ({level}) does not match index name ({self.name})"
)
return

# Integer-like levels
if lib.is_integer(level):
# Exclude bools (already handled above)
if level < 0 and level != -1:
raise IndexError(
"Too many levels: Index has only 1 level, "
f"{level} is not a valid level number"
Expand All @@ -2107,21 +2111,15 @@ def _validate_index_level(self, level) -> None:
raise IndexError(
f"Too many levels: Index has only 1 level, not {level + 1}"
)
return

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this is a better verification that validates what is expected from the documentation.

Suggested change
elif isinstance(level, str) and isinstance(self.name, str) and level != self.name:
raise KeyError(
f"Requested level ({level}) does not match index name ({self.name})"
)
# String level: only match if name is exactly the same string
elif isinstance(level, str) and not (
isinstance(self.name, str) and level == self.name
):
# For all other types, require exact match to index name
# Use pandas' isna for both level and self.name to catch NA-like names
if isna(self.name) or level != self.name:
raise KeyError(
f"Requested level ({level}) does not match index name ({self.name})"
)

# If level type is not int, str, or is NA, always raise KeyError
else:
raise KeyError(
f"Requested level ({level}) is not a valid level name or number"
)

def _get_level_number(self, level) -> int:
self._validate_index_level(level)
return 0
Expand Down
Loading