You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Issue with regenerate() — transport drops trigger, server doesn't delete stale messages #1012
regenerate() from useAgentChat fails with Anthropic models. The AI SDK correctly truncates messages client-side (removes last assistant message), but two issues in @cloudflare/ai-chat prevent it from working:
ws-chat-transport.ts drops the trigger field — AI SDK passes trigger: 'regenerate-message' to the transport, but the transport never includes it in the WebSocket body
persistMessages only UPSERTs, never DELETEs — when the client sends a truncated array, the old assistant message row stays in SQLite
Result: this.messages on the server still ends with the stale assistant message → Anthropic rejects with 400:
AI_APICallError: This model does not support assistant message prefill.
The conversation must end with a user message.
statusCode: 400
requestBodyValues.messages: [{ role: 'user', ... }, { role: 'assistant', ... }]
^^^^^^^^^^^^^^^^^^^^^^^^
stale — should have been deleted
The repro includes a side-by-side comparison: stock SDK (broken) vs a patched persistMessages that deletes stale rows (works).
Root cause
Transport (ws-chat-transport.ts):
// trigger is on options but never included in the bodyconstbodyPayload=JSON.stringify({messages: options.messages,
...extraBody,// trigger is NOT here});
Server (persistMessages in index.ts):
// UPSERT only — old rows never deletedthis.sql` insert into cf_ai_chat_agent_messages (id, message) values (${safe.id}, ${json}) on conflict(id) do update set message = excluded.message`;// Then reloads ALL rows from SQLite, including stale onesconstpersisted=this._loadMessagesFromDb();this.messages=autoTransformMessages(persisted);
Suggested fix
ws-chat-transport.ts — include trigger in the body:
Server handler — when trigger === 'regenerate-message', delete DB rows not in the incoming array:
constincomingIds=newSet(mergedMessages.map(m=>m.id));constallDbIds=this.sql`SELECT id FROM cf_ai_chat_agent_messages`.toArray();for(constrowofallDbIds){if(!incomingIds.has(row.id)){this.sql`DELETE FROM cf_ai_chat_agent_messages WHERE id = ${row.id}`;}}
Note: Fix mentioned is just a very rough patch to verify the root cause
Raised this with Claude, but verified in source it doesn't hallucinate -> seems like the regenerate trigger not sent from the client hook + server doesn't handle it
changed the title [-]regenerate() broken — transport drops trigger, server doesn't delete stale messages[/-][+]Issue with regenerate() — transport drops trigger, server doesn't delete stale messages[/+]on Feb 27, 2026
Tested the pkg.pr.new build from #1014 against our production AIChatAgent subclass (multi-workflow scoping, persistMessages override with metadata stamping).
Results — all three fixes confirmed working:
Regenerate — SDK's native regenerate() works, no Anthropic 400. We were manually truncating + resending as a workaround before this.
Stale row deletion — SQLite clean after multiple regenerates and edits. Our persistMessages override passes options through to super.persistMessages(), _deleteStaleRows works correctly.
Identical-content dedup — Forced two identical "Yes." assistant responses in the same conversation, navigated away and back, sent more messages. No duplicate rows (12 messages, all unique assistant_* IDs).
Previously had a content-based re-IDing workaround for #957 in our persistMessages override — removed it since this PR handles reconciliation upstream.
Activity
alexander-zuev commentedon Feb 27, 2026
Note: Fix mentioned is just a very rough patch to verify the root cause
Raised this with Claude, but verified in source it doesn't hallucinate -> seems like the regenerate trigger not sent from the client hook + server doesn't handle it
Before / After calling


regenerate():[-]regenerate() broken — transport drops trigger, server doesn't delete stale messages[/-][+]Issue with regenerate() — transport drops trigger, server doesn't delete stale messages[/+]threepointone commentedon Feb 27, 2026
Thanks for digging in here, will fix
fix(ai-chat): delete stale messages on regenerate, include trigger in…
threepointone commentedon Feb 27, 2026
can you try
npm i https://pkg.pr.new/cloudflare/agents/@cloudflare/ai-chat@1014alexander-zuev commentedon Feb 28, 2026
Tested the
pkg.pr.newbuild from #1014 against our productionAIChatAgentsubclass (multi-workflow scoping,persistMessagesoverride with metadata stamping).Results — all three fixes confirmed working:
regenerate()works, no Anthropic 400. We were manually truncating + resending as a workaround before this.persistMessagesoverride passesoptionsthrough tosuper.persistMessages(),_deleteStaleRowsworks correctly.assistant_*IDs).Previously had a content-based re-IDing workaround for #957 in our
persistMessagesoverride — removed it since this PR handles reconciliation upstream.threepointone commentedon Feb 28, 2026
You don't need to pass _deleteStaleRows
alexander-zuev commentedon Feb 28, 2026
Ok thx need some more coffee and I'll review more carefully!