Textualize/textual · error · TypeError

add_mode() must be called with a Screen type, not an instanc

Error message

add_mode() must be called with a Screen type, not an instance (got instance of {type(base_screen).__name__})

What it means

TypeError raised by App.add_mode when base_screen is an instantiated Screen rather than a type/callable, mirroring the MODES validation: modes store screen factories.

Source

Thrown at src/textual/app.py:2693

        return await_mount

    def add_mode(self, mode: str, base_screen: str | Callable[[], Screen]) -> None:
        """Adds a mode and its corresponding base screen to the app.

        Args:
            mode: The new mode.
            base_screen: The base screen associated with the given mode.

        Raises:
            InvalidModeError: If the name of the mode is not valid/duplicated.
        """
        if mode == "_default":
            raise InvalidModeError("Cannot use '_default' as a custom mode.")
        elif mode in self._modes:
            raise InvalidModeError(f"Duplicated mode name {mode!r}.")

        if isinstance(base_screen, Screen):
            raise TypeError(
                "add_mode() must be called with a Screen type, not an instance"
                f" (got instance of {type(base_screen).__name__})"
            )
        self._modes[mode] = base_screen

    def remove_mode(self, mode: str) -> AwaitComplete:
        """Removes a mode from the app.

        Screens that are running in the stack of that mode are scheduled for pruning.

        Args:
            mode: The mode to remove. It can't be the active mode.

        Raises:
            ActiveModeError: If trying to remove the active mode.
            UnknownModeError: If trying to remove an unknown mode.
        """
        if mode == self._current_mode:

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Pass the class: await app.add_mode("editor", EditorScreen)
  2. Pass a factory lambda if construction args are needed: lambda: EditorScreen(item)

Example fix

# before
await app.add_mode("editor", EditorScreen())

# after
await app.add_mode("editor", EditorScreen)
Defensive patterns

Strategy: type-guard

Validate before calling

assert not isinstance(base_screen, Screen), 'pass the Screen class'

Type guard

def is_screen_factory(v) -> bool:
    return isinstance(v, str) or (callable(v) and not isinstance(v, Screen))

Prevention

When it happens

Trigger: await app.add_mode("editor", EditorScreen()) — note the parentheses creating an instance.

Common situations: Easy slip of adding () when typing the call; passing a pre-built screen to share state.

Related errors


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