Commit a863c99
fix(copilot): make user-message persistence idempotent on message_id
persistUserMessage appended to copilot_chats.messages unconditionally
(messages || [userMsg]::jsonb) with no check that the id already exists.
A repeated POST for the same userMessageId — network retry, double
submit, React double-effect, or a bypassed/expired send lock (Redis-down
no-op) — therefore tacked on a duplicate array entry. The assistant
append in terminal-state.ts is already guarded; this brings the user
append to parity. (Evidence: 100% of duplicated message_ids in prod are
role=user.)
Guard the append with a containment check so it only concatenates when
the array doesn't already hold a message with this id:
CASE WHEN messages @> [{id}] THEN messages
ELSE messages || [userMsg] END
The client mints a fresh id per distinct send (verified across all hook
revisions), so a repeated id is always the same message — skipping is
safe and never drops a distinct message. conversationId/updatedAt stay
unconditional so the stream marker still advances on a retry. The
dual-write to copilot_messages is already idempotent (ON CONFLICT).
Verified on Postgres: same id -> stays 1 element; different id -> 2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>1 parent 75d9873 commit a863c99
1 file changed
Lines changed: 10 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
326 | 326 | | |
327 | 327 | | |
328 | 328 | | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
329 | 334 | | |
330 | 335 | | |
331 | 336 | | |
332 | | - | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
333 | 342 | | |
334 | 343 | | |
335 | 344 | | |
| |||
0 commit comments