{"id":"c4985b46664d9f47","repo":"sqlalchemy/sqlalchemy","slug":"can-only-concatenate-str-not-type-self-to-b","errorCode":null,"errorMessage":"Can only concatenate str (not '{type(self)}') to BitString","messagePattern":"Can only concatenate str \\(not '(.+?)'\\) to BitString","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/sqlalchemy/dialects/postgresql/bitstring.py","lineNumber":214,"sourceCode":"        return int(self, 2) if self else 0\n\n    def to_bytes(self, length: int = -1) -> bytes:\n        return int(self).to_bytes(\n            length if length >= 0 else self.octet_length, byteorder=\"big\"\n        )\n\n    def __bytes__(self) -> bytes:\n        return self.to_bytes()\n\n    def __getitem__(\n        self, key: SupportsIndex | slice[Any, Any, Any]\n    ) -> BitString:\n        return BitString(super().__getitem__(key), False)\n\n    def __add__(self, o: str) -> BitString:\n        \"\"\"Return self + o\"\"\"\n        if not isinstance(o, str):\n            raise TypeError(\n                f\"Can only concatenate str (not '{type(self)}') to BitString\"\n            )\n        return BitString(\"\".join([self, o]))\n\n    def __radd__(self, o: str) -> BitString:\n        if not isinstance(o, str):\n            raise TypeError(\n                f\"Can only concatenate str (not '{type(self)}') to BitString\"\n            )\n        return BitString(\"\".join([o, self]))\n\n    def __lshift__(self, amount: int) -> BitString:\n        \"\"\"Shifts each the bitstring to the left by the given amount.\n        String length is preserved::\n\n            BitString(\"000101\") << 1 == BitString(\"001010\")\n        \"\"\"\n        return BitString(","sourceCodeStart":196,"sourceCodeEnd":232,"githubUrl":"https://github.com/sqlalchemy/sqlalchemy/blob/d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff/lib/sqlalchemy/dialects/postgresql/bitstring.py#L196-L232","documentation":"Raised by BitString.__add__ (the `bs + other` operator) at lib/sqlalchemy/dialects/postgresql/bitstring.py:211-216 when the right-hand operand is not a str/BitString. BitString only supports concatenation with string-like operands to keep the result a valid bit string. NOTE: the message prints type(self) (always BitString) instead of type(o), so the reported type is misleading and does not reflect the offending operand.","triggerScenarios":"Executing BitString('01') + 1, BitString('01') + None, or BitString('01') + some_object where the right side is an int, bool, bytes, or custom type. Also via f-string/concatenation chains that assume implicit conversion.","commonSituations":"Assuming BitString behaves like int (it does support __int__) so arithmetic works; concatenating with an int flag instead of '1'/'0'; bytes vs str confusion; relying on the error message to debug and being misled because it always says 'BitString'.","solutions":["Convert the operand to a str of '0'/'1' first: bs + ('1' if flag else '0').","For ints use from_int then concatenate, or format explicitly: bs + format(value, 'b').","Do not trust the reported type in this message; inspect both operands manually."],"exampleFix":"// before\nresult = bits + flag  # flag is int 1\n// after\nresult = bits + ('1' if flag else '0')","handlingStrategy":"type-guard","validationCode":"if not isinstance(other, str):\n    raise TypeError(f'Cannot concatenate {type(other).__name__} to BitString')\nresult = bs + other","typeGuard":"def is_str_like(v) -> bool:\n    return isinstance(v, (str, BitString))","tryCatchPattern":"try:\n    result = bs + other\nexcept TypeError as e:\n    if 'concatenate' in str(e):\n        result = bs + str(other)  # coerce on purpose","preventionTips":["Convert operands with str(other) before concatenation when they may be non-str.","Type-annotate helper functions as accepting only str | BitString.","Run mypy/pyright to catch concatenation of incompatible types statically."],"tags":["bitstring","typeerror","operator-overloading","postgresql"],"analyzedSha":"d9b44cb731bd27e6e82c99a3c0fb598214e8e7ff","analyzedAt":"2026-08-01T17:20:52.075Z","schemaVersion":2}