Textualize/textual · error · DeclarationError

DeclarationError(error.name, error.token, error.message)

Error message

DeclarationError(error.name, error.token, error.message)

What it means

DOMNode.set_styles(css=...) parses the CSS string via parse_declarations; a DeclarationError from parsing is re-raised (detached from its internal cause) with the same name/token/message. So this exception means the inline CSS string you passed to set_styles contains an invalid declaration, not a problem with set_styles itself.

Source

Thrown at src/textual/css/query.py:433

        return app._prune(*self.nodes, parent=self._node)

    def set_styles(
        self, css: str | None = None, **update_styles
    ) -> DOMQuery[QueryType]:
        """Set styles on matched nodes.

        Args:
            css: CSS declarations to parser, or None.
        """
        _rich_traceback_omit = True

        for node in self:
            node.set_styles(**update_styles)
        if css is not None:
            try:
                new_styles = parse_declarations(css, read_from=("set_styles", ""))
            except DeclarationError as error:
                raise DeclarationError(error.name, error.token, error.message) from None
            for node in self:
                node._inline_styles.merge(new_styles)
                node.refresh(layout=True)
        return self

    def refresh(
        self, *, repaint: bool = True, layout: bool = False, recompose: bool = False
    ) -> DOMQuery[QueryType]:
        """Refresh matched nodes.

        Args:
            repaint: Repaint node(s).
            layout: Layout node(s).
            recompose: Recompose node(s).

        Returns:
            Query for chaining.
        """

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Inspect the re-raised DeclarationError fields (name, token, message) to find the offending declaration and fix the CSS string
  2. Validate generated CSS with parse_declarations during development/tests before calling set_styles
  3. Prefer keyword arguments (set_styles(color="red")) for simple cases to avoid string parsing

Example fix

# before
widget.set_styles(css="margin: 5x;")
# after
widget.set_styles(css="margin: 5;")  # or set_styles(margin=5)
Defensive patterns

Strategy: try-catch

Validate before calling

from textual.css.parse import parse_declarations
try:
    parse_declarations(css)
    valid = True
except Exception:
    valid = False

Try / catch

from textual.css.stylesheet import DeclarationError
try:
    widget.set_styles(css=css)
except DeclarationError as e:
    widget.set_styles(color="white")  # safe fallback

Prevention

When it happens

Trigger: `widget.set_styles(css="color: reddd; margin: 5x;")` — any bad color, unit, or unknown rule; dynamic f-string CSS with a bad interpolated value.

Common situations: Programmatically generated CSS strings with unvalidated values; copy-pasted TCSS snippets containing unsupported rules; typos in property names or units.

Related errors


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