Textualize/textual · error · InvalidModeError

Duplicated mode name {mode!r}.

Error message

Duplicated mode name {mode!r}.

What it means

InvalidModeError raised by App.add_mode when the mode name already exists in self._modes. Mode names must be unique; add_mode never overwrites.

Source

Thrown at src/textual/app.py:2690

        self.log.system(f"{self._current_mode!r} is the current mode")
        self.log.system(f"{self.screen} is active")

        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.

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Check membership first: if "editor" not in app._modes: await app.add_mode(...)
  2. Use remove_mode before re-adding a mode you want to replace
  3. Consolidate: declare all static modes in MODES and only add_mode for dynamic ones

Example fix

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

# after
if "editor" not in self._modes:
    await self.add_mode("editor", EditorScreen)
Defensive patterns

Strategy: validation

Validate before calling

if mode not in app._modes:
    await app.add_mode(mode, screen_cls)

Try / catch

try:
    await app.add_mode(mode, screen_cls)
except InvalidModeError:
    await app.remove_mode(mode)
    await app.add_mode(mode, screen_cls)

Prevention

When it happens

Trigger: Calling add_mode("editor", ...) twice, or add_mode with a name already declared in the MODES class variable.

Common situations: Repeated init/on_mount calls registering modes; merging runtime modes with class-declared ones without checking existence.

Related errors


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