From a6dd25720c3f468a06567167823a7f98e4bc3174 Mon Sep 17 00:00:00 2001 From: Abhay Singh Date: Thu, 11 Jun 2026 08:33:10 -0400 Subject: [PATCH] fix: guard migration meta cleanup against scalar jsonb values The meta-strip UPDATE in 9228797f839a crashed on prod with "cannot delete from scalar": at least one conversations.meta holds a bare JSON scalar, and the jsonb `-` operator only works on objects. The aborted deploy left the migration rolled back (single transaction), so re-running the guarded version is safe. Scalar meta rows can't contain the prompt keys anyway, so skipping them is correct. Verified locally by downgrading to d740e0090bdc, seeding open conversations with scalar meta (string and number), and upgrading: merge collapses them, scalar values pass through untouched. Co-Authored-By: Claude Fable 5 --- .../9228797f839a_single_open_conversation_per_user.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/alembic/versions/9228797f839a_single_open_conversation_per_user.py b/alembic/versions/9228797f839a_single_open_conversation_per_user.py index ff760b3..da82e77 100644 --- a/alembic/versions/9228797f839a_single_open_conversation_per_user.py +++ b/alembic/versions/9228797f839a_single_open_conversation_per_user.py @@ -74,12 +74,14 @@ def upgrade() -> None: op.execute("DROP TABLE conv_keepers") # Per-request prompt data now lives on the bot utterance's generation snapshot. + # jsonb_typeof guard: the `-` operator raises "cannot delete from scalar" on + # rows whose meta is a bare JSON scalar rather than an object. op.execute( """ UPDATE conversations SET meta = meta - 'texet_instruction_prompt' - 'texet_day_number' - 'texet_user_local_time' - WHERE meta IS NOT NULL + WHERE meta IS NOT NULL AND jsonb_typeof(meta) = 'object' """ )