slint-ui/slint · error · NotImplementedError

does not support removing rows

Error message

{type(self).__name__} does not support removing rows

What it means

The base Model class's remove_row default implementation raises NotImplementedError because a generic model cannot delete rows. Subclasses must override remove_row (and call notify_row_removed) to support row deletion.

Solutions

  1. Use a model that supports deletion, e.g. slint.ListModel, which implements remove_row.
  2. In a custom model subclass, override remove_row to delete the backing data and call self.notify_row_removed(row, 1).
  3. Restructure the UI to not delete rows from this model if mutation is intentionally unsupported.

Example fix

# before
class MyModel(slint.Model):
    def row_count(self): return len(self.data)

# after
class MyModel(slint.Model):
    def row_count(self): return len(self.data)
    def remove_row(self, row):
        del self.data[row]
        self.notify_row_removed(row, 1)
Defensive patterns

Strategy: type-guard

Validate before calling

def supports_remove(model):
    return type(model).remove_row is not slint.Model.remove_row

Type guard

def supports_remove(model):
    return isinstance(model, slint.ListModel) or overrides(model, "remove_row")

Try / catch

try:
    model.remove_row(idx)
except NotImplementedError:
    rebuild_model_without(idx)

Prevention

When it happens

Trigger: Calling model.remove_row(index) on a model instance (or subclass that did not override remove_row), e.g. on a Model or ListModel-like object that only implements read access.

Common situations: Passing a read-only or custom model to UI code (ListView with swipe-to-delete) that invokes remove_row; forgetting to override remove_row when subclassing slint.Model.

Related errors


AI-assisted analysis of slint-ui/slint@3a7e700487 (2026-09-16). Data as JSON: /api/errors/60f8b681d0254284. Report an issue: GitHub.

Appendix: source

Thrown at api/python/slint/slint/models.py:69

        ...

    @abstractmethod
    def row_data(self, row: int) -> T | None:
        """Returns the data for the given row.
        Re-implement this method in a sub-class to provide the data."""
        ...

    def push_row(self, value: T) -> None:
        """Add a new row to the model with the provided value.
        The default implementation calls `insert_row` with the row count."""
        self.insert_row(self.row_count(), value)

    def remove_row(self, row: int) -> None:
        """Remove the row at the given index.
        Raises an exception when the model rejects the modification.
        The default implementation raises NotImplementedError. A model that
        supports removing rows should also call `notify_row_removed`."""
        raise NotImplementedError(
            f"{type(self).__name__} does not support removing rows"
        )

    def insert_row(self, row: int, value: T) -> None:
        """Insert a new row at the given index.
        Raises an exception when the model rejects the modification.
        The default implementation raises NotImplementedError. A model that
        supports inserting rows should also call `notify_row_added`."""
        raise NotImplementedError(
            f"{type(self).__name__} does not support inserting rows"
        )

    def notify_row_changed(self, row: int) -> None:
        """Call this method from a sub-class to notify the views that a row has changed."""
        super().notify_row_changed(row)

    def notify_row_removed(self, row: int, count: int) -> None:
        """Call this method from a sub-class to notify the views that

View on GitHub (pinned to 3a7e700487)