fix(backfill): store full UIMessage in chat_messages.parts#627
Conversation
The workflow persists the entire UIMessage in the parts column
(persistLatestUserMessage / persistAssistantMessage), and the read path
(getSessionChatHandler) returns parts verbatim as a UIMessage. The Phase 2
backfill wrote only the bare parts array, so migrated history came back
without id/role and wouldn't render through the workflow read path.
Store { id, role, parts } to match the native shape. The already-migrated
~46k rows were corrected in place via a one-time SQL reconstruction
(jsonb_build_object from the id/role/parts columns); this fix keeps the
owed straggler re-run consistent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedReview was skipped due to path filters ⛔ Files ignored due to path filters (2)
CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Architecture diagram
sequenceDiagram
participant B as Backfill Script
participant DB as Database
participant R as Read Path
participant W as Native Write Path
Note over B,W: Chat Messages Data Flow
B->>B: Read migrated rows
B->>DB: Insert chat_messages row
Note over B,DB: parts: { id, role, parts } (full UIMessage)
alt Native write path
W->>DB: insert chat_messages.parts as UIMessage
Note over W,DB: persistLatestUserMessage / persistAssistantMessage
W->>W: parts = message as never (full UIMessage)
end
DB-->>R: Return rows
R->>R: messages = rows.map(r => r.parts)
Note over R: Expects each .parts to be UIMessage
alt parts is full UIMessage object
R->>R: Extract id, role, parts from object
R-->>R: Render correctly
else parts is bare array (legacy backfill)
R->>R: Missing id and role
R-->>R: Render failure (no id/role)
end
Note over B,R: Fix: Backfill now stores { id, role, parts }<br/>matching native shape
opt Production data fix (already applied)
B->>DB: UPDATE chat_messages
Note over B,DB: Reconstruct from columns<br/>where parts is array
DB-->>B: Verify: 0 array rows<br/>0 missing id/role/parts
end
Auto-approved: This is a focused, low-risk fix to a backfill script that corrects the stored shape of chat messages to match the production read path, has a corresponding test update, and the production data was already reconciled via a separate SQL command.
Re-trigger cubic
Summary
The chat-workflow cutover (recoupable/chat#1747) needs migrated history to read back through the workflow path. That surfaced a shape mismatch in the Phase 2 backfill:
UIMessageinchat_messages.parts—persistLatestUserMessage.ts:42andpersistAssistantMessage.ts:27both doparts: message as never.getSessionChatHandler.ts:44returnsmessages: rows.map(r => r.parts)and expects each to already be aUIMessage.parts: content.parts— just the bare parts array — so migrated rows came back with noid/roleand wouldn't render.This stores
{ id, role, parts }to match the native shape.Data already corrected
The ~46k already-migrated rows were fixed in place on prod via a one-time, reversible SQL reconstruction from the existing columns (the original array is preserved nested under
parts):Post-update verification: 46,616 object rows / 0 array rows; 0 rows missing
id/role/partskeys; 0 rows where innerid/rolediverge from the columns.This code change keeps the owed pre-promotion straggler re-run consistent (write-once, so it only adds new rows in the correct shape).
Test plan
migrateRoomunit test assertspartsis the full{ id, role, parts }UIMessage. (4 tests green)tsc --noEmitclean on changed files;eslintclean.🤖 Generated with Claude Code