Textualize/textual · error · TokenError

{expect.description} (found {error_line.split(';')[0]!r}). ;

Error message

{expect.description} (found {error_line.split(';')[0]!r}). ; Did you forget a semicolon at the end of a line?

What it means

TokenError raised when the tokenizer encounters text that doesn't match the expected token pattern at the current position. The message embeds the expectation description and the offending text (up to ';'), plus a semicolon hint when a declaration end was expected.

Source

Thrown at src/textual/css/tokenizer.py:298

                    self.read_from,
                    self.code,
                    (line_no, col_no),
                    referenced_by=None,
                )

                return token

        else:
            match = expect.match(line, col_no)

        if match is None:
            error_line = line[col_no:]
            error_message = (
                f"{expect.description} (found {error_line.split(';')[0]!r})."
            )
            if expect._expect_semicolon and not error_line.endswith(";"):
                error_message += "; Did you forget a semicolon at the end of a line?"
            raise TokenError(
                self.read_from, self.code, (line_no + 1, col_no + 1), error_message
            )

        for name, value in zip(expect.names, match.groups()[1:]):
            if value is not None:
                break
        else:
            # For MyPy's benefit
            raise AssertionError("can't reach here")

        token = Token(
            name,
            value,
            self.read_from,
            self.code,
            (line_no, col_no),
            referenced_by=None,
        )

View on GitHub (pinned to 06dbeef4bb)

Solutions

  1. Terminate each declaration with ';'
  2. Correct the value so it matches the expected grammar (scalar, color, keyword)
  3. Look at the 'found ...' portion of the message to identify the offending text

Example fix

/* before */
#box {
  width: 10
  height: 5;
}
/* after */
#box {
  width: 10;
  height: 5;
}
Defensive patterns

Strategy: validation

Validate before calling

import re
_DECL = re.compile(r'^[-a-zA-Z]+\s*:\s*[^;{]+;\s*$', re.M)
def declarations_well_formed(css: str) -> bool:
    return all(_DECL.match(line) or not ':' in line for line in css.splitlines())

Try / catch

from textual.css.tokenizer import TokenError
try:
    stylesheet.parse()
except TokenError as e:
    report(f"CSS syntax error at {e.location}: {e}")

Prevention

When it happens

Trigger: A declaration line whose value doesn't parse, e.g. 'width: ten;' or a stray character inside a rule block. The hint 'Did you forget a semicolon...' appears when the next line continues a declaration that wasn't terminated.

Common situations: Missing semicolons between declarations (especially when merging lines), invalid value syntax, stray whitespace/comments in unexpected places.

Related errors


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