Textualize/textual · error · UnresolvedVariableError

reference to undefined variable '${variable_name}'; did you

Error message

reference to undefined variable '${variable_name}'; did you mean '${suggested_variable}'?

What it means

During CSS variable substitution (substitute_references), Textual resolves $variable references against defined variables. An undefined reference raises UnresolvedVariableError with source position; if a similarly named variable exists, get_suggestion appends a 'did you mean' hint.

Source

Thrown at src/textual/css/parse.py:359


def _unresolved(variable_name: str, variables: Iterable[str], token: Token) -> NoReturn:
    """Raise a TokenError regarding an unresolved variable.

    Args:
        variable_name: A variable name.
        variables: Possible choices used to generate suggestion.
        token: The Token.

    Raises:
        UnresolvedVariableError: Always raises a TokenError.
    """
    message = f"reference to undefined variable '${variable_name}'"
    suggested_variable = get_suggestion(variable_name, list(variables))
    if suggested_variable:
        message += f"; did you mean '${suggested_variable}'?"

    raise UnresolvedVariableError(
        token.read_from,
        token.code,
        token.start,
        message,
        end=token.end,
    )


def substitute_references(
    tokens: Iterable[Token], css_variables: dict[str, list[Token]] | None = None
) -> Iterable[Token]:
    """Replace variable references with values by substituting variable reference
    tokens with the tokens representing their values.

    Args:
        tokens: Iterator of Tokens which may contain tokens
            with the name "variable_ref".

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Use the suggested variable from the 'did you mean' hint if present
  2. Define the variable with `$name: value;` in the same CSS (or a higher DEFAULT_CSS) before use
  3. Search all .tcss/py CSS strings for the exact $reference after renames

Example fix

/* before */
$accnet: ansi_red;
background: $accnet;
/* after */
$accent: ansi_red;
background: $accent;
Defensive patterns

Strategy: validation

Validate before calling

import re
refs = set(re.findall(r"\$([\w-]+)", css_text))
defined = set(re.findall(r"\$([\w-]+)\s*:", css_text))
missing = refs - defined
assert not missing, missing

Try / catch

from textual.css.errors import UnresolvedVariableError
try:
    ...
except UnresolvedVariableError as e:
    # e.g. add the variable or fix the reference

Prevention

When it happens

Trigger: `$accnet` in a tcss when only `$accent` is defined; using `$var` defined in a different scope/component; typos or renaming a variable without updating all usages.

Common situations: Renaming design-token variables and missing call sites; referencing variables defined in another widget's CSS; upgrading a theme where a variable was removed.

Related errors


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