sqlalchemy/sqlalchemy · error · TypeError
Can only concatenate str (not '{type(self)}') to BitString
Error message
Can only concatenate str (not '{type(self)}') to BitString What it means
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.
Source
Thrown at lib/sqlalchemy/dialects/postgresql/bitstring.py:214
return int(self, 2) if self else 0
def to_bytes(self, length: int = -1) -> bytes:
return int(self).to_bytes(
length if length >= 0 else self.octet_length, byteorder="big"
)
def __bytes__(self) -> bytes:
return self.to_bytes()
def __getitem__(
self, key: SupportsIndex | slice[Any, Any, Any]
) -> BitString:
return BitString(super().__getitem__(key), False)
def __add__(self, o: str) -> BitString:
"""Return self + o"""
if not isinstance(o, str):
raise TypeError(
f"Can only concatenate str (not '{type(self)}') to BitString"
)
return BitString("".join([self, o]))
def __radd__(self, o: str) -> BitString:
if not isinstance(o, str):
raise TypeError(
f"Can only concatenate str (not '{type(self)}') to BitString"
)
return BitString("".join([o, self]))
def __lshift__(self, amount: int) -> BitString:
"""Shifts each the bitstring to the left by the given amount.
String length is preserved::
BitString("000101") << 1 == BitString("001010")
"""
return BitString(View on GitHub (pinned to d9b44cb731)
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.
Example fix
// before
result = bits + flag # flag is int 1
// after
result = bits + ('1' if flag else '0') Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(other, str):
raise TypeError(f'Cannot concatenate {type(other).__name__} to BitString')
result = bs + other Type guard
def is_str_like(v) -> bool:
return isinstance(v, (str, BitString)) Try / catch
try:
result = bs + other
except TypeError as e:
if 'concatenate' in str(e):
result = bs + str(other) # coerce on purpose Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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'.
Related errors
- Operands must be the same length
- BitString must only contain '0' and '1' chars
- value must be non-negative
- length must be non-negative
- Cannot encode {value} as a BitString of length {length}
AI-assisted analysis of sqlalchemy/sqlalchemy@d9b44cb731 (2026-08-01).
Data as JSON: /data/errors/c4985b46664d9f47.json.
Report an issue: GitHub.