{"record":{"id":"df8a42870276ec42","repo":"Textualize/textual","slug":"expect-description-found-error-line-split","errorCode":null,"errorMessage":"{expect.description} (found {error_line.split(';')[0]!r}). ; Did you forget a semicolon at the end of a line?","messagePattern":"(.+?) \\(found (.+?)\\)\\. ; Did you forget a semicolon at the end of a line\\?","errorType":"exception","errorClass":"TokenError","httpStatus":null,"severity":"error","filePath":"src/textual/css/tokenizer.py","lineNumber":298,"sourceCode":"                    self.read_from,\n                    self.code,\n                    (line_no, col_no),\n                    referenced_by=None,\n                )\n\n                return token\n\n        else:\n            match = expect.match(line, col_no)\n\n        if match is None:\n            error_line = line[col_no:]\n            error_message = (\n                f\"{expect.description} (found {error_line.split(';')[0]!r}).\"\n            )\n            if expect._expect_semicolon and not error_line.endswith(\";\"):\n                error_message += \"; Did you forget a semicolon at the end of a line?\"\n            raise TokenError(\n                self.read_from, self.code, (line_no + 1, col_no + 1), error_message\n            )\n\n        for name, value in zip(expect.names, match.groups()[1:]):\n            if value is not None:\n                break\n        else:\n            # For MyPy's benefit\n            raise AssertionError(\"can't reach here\")\n\n        token = Token(\n            name,\n            value,\n            self.read_from,\n            self.code,\n            (line_no, col_no),\n            referenced_by=None,\n        )","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/css/tokenizer.py#L280-L316","documentation":"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.","triggerScenarios":"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.","commonSituations":"Missing semicolons between declarations (especially when merging lines), invalid value syntax, stray whitespace/comments in unexpected places.","solutions":["Terminate each declaration with ';'","Correct the value so it matches the expected grammar (scalar, color, keyword)","Look at the 'found ...' portion of the message to identify the offending text"],"exampleFix":"/* before */\n#box {\n  width: 10\n  height: 5;\n}\n/* after */\n#box {\n  width: 10;\n  height: 5;\n}","handlingStrategy":"validation","validationCode":"import re\n_DECL = re.compile(r'^[-a-zA-Z]+\\s*:\\s*[^;{]+;\\s*$', re.M)\ndef declarations_well_formed(css: str) -> bool:\n    return all(_DECL.match(line) or not ':' in line for line in css.splitlines())","typeGuard":null,"tryCatchPattern":"from textual.css.tokenizer import TokenError\ntry:\n    stylesheet.parse()\nexcept TokenError as e:\n    report(f\"CSS syntax error at {e.location}: {e}\")","preventionTips":["Always end declarations with ';'","Check the 'found ...' text in the message","Run a CSS parse check in CI"],"tags":["textual","css","tokenizer","syntax"],"backgroundTag":"css-syntax-error","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}