Textualize/textual · error · StyleTypeError

{self.name} must be a str

Error message

{self.name} must be a str

What it means

The NameProperty descriptor (used for the `layer`-like name rules such as `link`-style names) requires either None (to clear the rule) or a Python str. Passing any other type (int, list, Color, etc.) raises StyleTypeError. This guards the internal rule storage which only accepts string identifiers.

Source

Thrown at src/textual/css/_style_properties.py:932

        return obj.get_rule(self.name, "")  # type: ignore[return-value]

    def __set__(self, obj: StylesBase, name: str | None):
        """Set the name property.

        Args:
            obj: The ``Styles`` object.
            name: The name to set the property to.

        Raises:
            StyleTypeError: If the value is not a ``str``.
        """
        _rich_traceback_omit = True
        if name is None:
            if obj.clear_rule(self.name):
                obj.refresh(layout=True)
        else:
            if not isinstance(name, str):
                raise StyleTypeError(f"{self.name} must be a str")
            if obj.set_rule(self.name, name):
                obj.refresh(layout=True)


class NameListProperty:
    def __set_name__(self, owner: StylesBase, name: str) -> None:
        self.name = name

    def __get__(
        self, obj: StylesBase, objtype: type[StylesBase] | None = None
    ) -> tuple[str, ...]:
        return obj.get_rule(self.name, ())  # type: ignore[return-value]

    def __set__(self, obj: StylesBase, names: str | tuple[str] | None = None):
        _rich_traceback_omit = True
        if names is None:
            if obj.clear_rule(self.name):
                obj.refresh(layout=True)

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Coerce the value to str before assignment, or pass None to clear the rule
  2. Validate external config values with a type check before applying them to styles

Example fix

# before
styles.link_id = 42
# after
styles.link_id = str(42)  # or None to clear
Defensive patterns

Strategy: type-guard

Validate before calling

if name is None or isinstance(name, str):
    styles.link_id = name

Type guard

def is_style_name(v) -> bool:
    return v is None or isinstance(v, str)

Prevention

When it happens

Trigger: `styles.link_id = 42`, `styles.<name-rule> = ['a','b']`, or passing a non-str variable from user input into a name-style assignment instead of a string or None.

Common situations: Programmatically building styles from unvalidated data (JSON config, DB rows) where the name field is a number; forgetting that None clears the rule while other falsy values like 0 do not.

Related errors


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