fix(state): drop unknown BLOB columns before messages reach the API

SELECT * in every message reader (get_messages, get_messages_around)
hands every column straight into a dict that FastAPI serializes to
JSON. FastAPI's encoder calls .decode() on any raw bytes value and
raises UnicodeDecodeError the moment it isn't valid utf-8 -- this
already happened for display_identity BLOB before it got an explicit
pop, and the next binary column added to the messages table would
repeat it with no defense in the reader.

_row_to_message_dict now strips any remaining bytes/bytearray value
generically, so a future BLOB column can't take the whole endpoint
down regardless of whether its pop was remembered.

Fixes #116510
This commit is contained in:
chelsealong
2026-09-20 00:45:27 +00:00
committed by Teknium
parent 2b86e0b223
commit b873a3a1d9
2 changed files with 41 additions and 0 deletions

View File

@@ -866,6 +866,12 @@ class SessionMessagesMixin:
msg["tool_calls"], [], f"Failed to deserialize tool_calls in {warn_context}, falling back to []")
if msg.get("display_metadata") is not None:
msg["display_metadata"] = self._decode_display_metadata(msg["display_metadata"])
# A `SELECT *` picks up every column, including any BLOB added to the schema later; the
# JSON encoder that serves these dicts over HTTP fails outright on raw bytes. Drop them
# here, once, rather than needing a new named pop for each future binary column.
for key, value in list(msg.items()):
if isinstance(value, (bytes, bytearray)):
msg.pop(key)
return msg
@staticmethod