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._data

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Guard the lookup: if key in table._row_locations or catch RowDoesNotExist around get_row_index.
  2. Handle rows being removed between event and handler by refreshing state before lookup.
  3. Use the key returned from add_row rather than reconstructing keys manually.
  4. 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

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


AI-assisted analysis of Textualize/textual@06dbeef4bb (2026-08-27). Data as JSON: /api/errors/1b92c64dad84c484. Report an issue: GitHub.