{"record":{"id":"c2156287ee371c8e","repo":"Textualize/rich","slug":"only-str-or-text-can-be-appended-to-text","errorCode":null,"errorMessage":"Only str or Text can be appended to Text","messagePattern":"Only str or Text can be appended to Text","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"rich/text.py","lineNumber":978,"sourceCode":"                self.pad_right(excess_space - left, character)\n            else:\n                self.pad_left(excess_space, character)\n\n    def append(\n        self, text: Union[\"Text\", str], style: Optional[Union[str, \"Style\"]] = None\n    ) -> \"Text\":\n        \"\"\"Add text with an optional style.\n\n        Args:\n            text (Union[Text, str]): A str or Text to append.\n            style (str, optional): A style name. Defaults to None.\n\n        Returns:\n            Text: Returns self for chaining.\n        \"\"\"\n\n        if not isinstance(text, (str, Text)):\n            raise TypeError(\"Only str or Text can be appended to Text\")\n\n        if len(text):\n            if isinstance(text, str):\n                sanitized_text = strip_control_codes(text)\n                self._text.append(sanitized_text)\n                offset = len(self)\n                text_length = len(sanitized_text)\n                if style:\n                    self._spans.append(Span(offset, offset + text_length, style))\n                self._length += text_length\n            elif isinstance(text, Text):\n                _Span = Span\n                if style is not None:\n                    raise ValueError(\n                        \"style must not be set when appending Text instance\"\n                    )\n                text_length = self._length\n                if text.style:","sourceCodeStart":960,"sourceCodeEnd":996,"githubUrl":"https://github.com/Textualize/rich/blob/9d8f9a372cc5916fd4781fec207ced7ddac2f08f/rich/text.py#L960-L996","documentation":"Text.append(text, style=None) only accepts str or Text instances — anything else raises TypeError('Only str or Text can be appended to Text'). The restriction exists because append must copy spans and sanitize control codes, which is only defined for those two types; there is no implicit str() coercion of numbers, styled tuples, or other renderables.","triggerScenarios":"text.append(42), text.append(3.14), text.append(None), text.append(some_renderable), or text.append(b'bytes'). The isinstance check runs before any length test, so even 'empty-looking' wrong types raise.","commonSituations":"Building log/table cells by concatenating computed numeric values without str(); mixing rich Text with plain Python types in f-string-free code paths; appending bytes from a network layer; passing a Panel/Table/other renderable where its text was intended.","solutions":["Convert non-text values first: text.append(str(value)).","For other rich renderables, don't append — use Columns/Group or a render group instead of Text concatenation.","Decode bytes before appending: text.append(data.decode('utf-8'))."],"exampleFix":"# before\ntext.append(count)  # TypeError if count is int\n\n# after\ntext.append(str(count))","handlingStrategy":"type-guard","validationCode":"value = value if isinstance(value, (str, Text)) else str(value)\ntext.append(value, style=style)","typeGuard":"from rich.text import Text\nfrom typing import Union\n\ndef appendable(value: object) -> Union[str, Text]:\n    \"\"\"Coerce anything to a Text-appendable value.\"\"\"\n    return value if isinstance(value, (str, Text)) else str(value)","tryCatchPattern":"try:\n    t.append(v)\nexcept TypeError:\n    t.append(str(v))","preventionTips":["str() numeric/None/bytes values before appending to Text.","In generic helpers, coerce with a type guard rather than trusting callers."],"tags":["rich","text","typeerror","type-check","append"],"backgroundTag":null,"analyzedSha":"9d8f9a372cc5916fd4781fec207ced7ddac2f08f","analyzedAt":"2026-08-15T03:30:11.781Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}