Textualize/textual · error · RowDoesNotExist
No row exists for row_key={row_key!r}
Error message
No row exists for row_key={row_key!r} What it means
Raised by DataTable.get_row_index when row_key is not in _row_locations. This is the key-to-index lookup used to find where a row currently sits; an unknown key means the row was never added or has since been removed/cleared.
Source
Thrown at src/textual/widgets/_data_table.py:1043
if not self.is_valid_row_index(row_index):
raise RowDoesNotExist(f"Row index {row_index!r} is not valid.")
row_key = self._row_locations.get_key(row_index)
return self.get_row(row_key)
def get_row_index(self, row_key: RowKey | str) -> int:
"""Return the current index for the row identified by row_key.
Args:
row_key: The row key to find the current index of.
Returns:
The current index of the specified row key.
Raises:
RowDoesNotExist: If the row key does not exist.
"""
if row_key not in self._row_locations:
raise RowDoesNotExist(f"No row exists for row_key={row_key!r}")
return self._row_locations.get(row_key)
def get_column(self, column_key: ColumnKey | str) -> Iterable[CellType]:
"""Get the values from the column identified by the given column key.
Args:
column_key: The key of the column.
Returns:
A generator which yields the cells in the column.
Raises:
ColumnDoesNotExist: If there is no column corresponding to the key.
"""
if column_key not in self._column_locations:
raise ColumnDoesNotExist(f"Column key {column_key!r} is not valid.")
data = self._dataView on GitHub (pinned to 06dbeef4bb)
Solutions
- Guard the lookup: if key in table._row_locations or catch RowDoesNotExist around get_row_index.
- Handle rows being removed between event and handler by refreshing state before lookup.
- Use the key returned from add_row rather than reconstructing keys manually.
- After clear(), discard all previously saved keys.
Example fix
# before
index = table.get_row_index(row_key)
# after
from textual.widgets._data_table import RowDoesNotExist
try:
index = table.get_row_index(row_key)
except RowDoesNotExist:
index = -1 Defensive patterns
Strategy: try-catch
Validate before calling
index = table.get_row_index(key) if key in table.row_keys else -1
Try / catch
from textual.widgets._data_table import RowDoesNotExist
try:
idx = table.get_row_index(row_key)
except RowDoesNotExist:
idx = -1 Prevention
- Treat row keys as ephemeral after mutations
- Validate event-supplied keys before use
- Discard saved keys on clear()
When it happens
Trigger: Calling get_row_index with a string/RowKey that does not match any row added via add_row; using keys after clear(); mixing keys between DataTable instances.
Common situations: Translating row keys to indices after a table rebuild; handling DataTableRowSelected/DataTableRowCursorMoved events for rows already deleted; storing event row keys and replaying them later.
Related errors
- Row key {row_key!r} is not valid.
- Column key {column_key!r} is not valid.
- No column exists for column_key={column_key!r}
- Row index {row_index!r} is not valid.
- Column index {column_index!r} is not valid.
AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27).
Data as JSON: /api/errors/1b92c64dad84c484.
Report an issue: GitHub.