Textualize/textual · error · CSSPathError

Expected a str, Path or list[str | Path] for the CSS_PATH.

Error message

Expected a str, Path or list[str | Path] for the CSS_PATH.

What it means

CSSPathError raised by textual's CSS path normalization when the CSS_PATH class variable is not a str, Path/PurePath, or a list of those. The App constructor validates CSS_PATH before mounting.

Source

Thrown at src/textual/_path.py:42

    Args:
        css_path: Value to be normalized.

    Raises:
        CSSPathError: If the argument has the wrong format.

    Returns:
        A list of paths.
    """

    paths: list[PurePath] = []
    if isinstance(css_path, str):
        paths = [Path(css_path)]
    elif isinstance(css_path, PurePath):
        paths = [css_path]
    elif isinstance(css_path, list):
        paths = [Path(path) for path in css_path]
    else:
        raise CSSPathError("Expected a str, Path or list[str | Path] for the CSS_PATH.")

    return paths


def _make_path_object_relative(path: str | PurePath, obj: object) -> Path:
    """Convert the supplied path to a Path object that is relative to a given Python object.
    If the supplied path is absolute, it will simply be converted to a Path object.
    Used, for example, to return the path of a CSS file relative to a Textual App instance.

    Args:
        path: A path.
        obj: A Python object to resolve the path relative to.

    Returns:
        A resolved Path object, relative to obj
    """
    path = Path(path)

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Use a plain string CSS_PATH = "app.css" or a Path object
  2. If multiple stylesheets, use an explicit list: CSS_PATH = ["a.css", "b.css"]
  3. Convert other iterables to list before assigning: CSS_PATH = list(paths)

Example fix

# before
class MyApp(App):
    CSS_PATH = ("app.css", "extra.css")

# after
class MyApp(App):
    CSS_PATH = ["app.css", "extra.css"]
Defensive patterns

Strategy: type-guard

Validate before calling

from pathlib import Path
css = ('app.css', 'extra.css')
assert isinstance(css, (str, Path, list)), 'CSS_PATH must be str/Path/list'

Type guard

def valid_css_path(p) -> bool:
    import pathlib
    return isinstance(p, (str, pathlib.Path, pathlib.PurePath)) or (
        isinstance(p, list) and all(isinstance(x, (str, pathlib.Path)) for x in p)
    )

Try / catch

try:
    app.run()
except CSSPathError:
    app.CSS_PATH = [str(p) for p in app.CSS_PATH]  # then retry

Prevention

When it happens

Trigger: Setting CSS_PATH = ('app.css', 'extra.css') (a tuple), a set, None, or a dict on an App subclass and then running it.

Common situations: Developers switch from list to tuple literal, refactor CSS_PATH dynamically, or copy-paste configs from other frameworks expecting different types.

Related errors


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